License

There are not guarantees or assurances provided, all examples are selected for demonstration purposes.

MIT

Copyright (c) 2020-2021 by Gustavo Zambrana

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Setup

Python Libraries

In [1]:
import os
print( os.environ['PYTHONPATH'] )
%reload_ext autoreload
%autoreload 2


# Python ≥3.6 is required
import sys
assert sys.version_info >= (3, 6)

# Common imports
import numpy as np
import os
import pandas as pd
import yfinance as yf
import feather
import tables
import ta
from datetime import datetime

# Ignore useless warnings (see SciPy issue #5998)
import warnings
warnings.filterwarnings(action="ignore", message="^internal gelsd")

import sqlalchemy
print(sqlalchemy.__version__)
from sqlalchemy.orm import with_polymorphic

from trade_engine.persist.DBLayer                             import DBLayer
from trade_engine.persist.DBSchema                            import DBSchema
/Users/gustavozambrana/Google Drive/Python/Projects/Trade_Engine/src:/Users/gustavozambrana/Google Drive/Python:/Users/gustavozambrana/Google Drive/Python/Projects/Market_Data/src
1.4.0b3

Logging

In [2]:
import logging
from logging.config import fileConfig
fileConfig('/Users/gustavozambrana/Google Drive/Python/Projects/Trade_Engine/log/logging.ini')

#logger = logging.getLogger('dev')
import logging
logging.basicConfig(level=logging.INFO)
logging.getLogger().setLevel(logging.INFO)

Database

In [3]:
myDBLayer = DBLayer()

# ***
# *** Connect String for SQL Lite db in memory
# ***
# sqliteConnString = 'sqlite:///:memory:' 
# myDBLayer.connect( connString = sqliteConnString )

# ***
# *** Connect String for SQL Lite db file
# ***

# dbTradeEngTestPath = '/Users/gustavozambrana/Google Drive/Python/Projects/Trade_Engine/db/dbTradeEngTest.db'
# ConnString = 'sqlite:///' + dbTradeEngTestPath

# ***
# *** Postgres DB
# ***

ConnString = 'postgresql+pg8000://postgres:postgres@localhost:7777/trade_engine_dev_db'

# *** Connect to DB, Create DB Schema if not already created, and acquired a DB session

myDBLayer.connect( connString = ConnString )
DBSchema.createDBSchema()  
session = DBLayer.getSession()
conn string =  postgresql+pg8000://postgres:postgres@localhost:7777/trade_engine_dev_db

Optional Drop Table(s)

In [4]:
DBSchema.dropAll()

Trade Engine Overview

Architecture

  • The purpose of the engine is:

    • Performs a backtest for a single trade strategy or a portfolio of trade strategies

    • Support different kinds of backtests and optimizations of hyper-parameters per trade strategy

    • Analyzed out-of-sample performance for trade strategies and/or portfolio

      • Support Technical Analysis Models, as well as AI Based Models to manage all trade actions, that is:

        • Enter, Exit, Position Sizing, Stop-Loss, Trail-Stop-Loss, etc.

        • Technical Analysis Models are modelts that:

          • Do not need to be fitted prior to a backtest, such as: SMA, RSI, Bollinger Bands, MACD, etc.
        • AI Based Models are any models that:

          • Required to be fitted with a training and validation date ranges that do not overlapped the backtest period, such as Machine Learning, Deep Learning, and Reinformcement Learning Models.
    • Support ensemble models for any trade action in a Trade Strategy, i.e.:

      • N number of models for entering a trade
      • M number of models to exit a trade
      • K number of models to decide on stop-loss %
    • Support mixing Technical Analysis and AI Based Models in ensembles

    • Support persisting all information to execute a backtest in a Relational Database, as well as the results

    • Setup the initial architecture to enable distributed cloud execution of backtests (future)

  • A **Trade Strategy** is defined via a Trade Asset Register Item, which is an object that contains all components necessary to execute in a backtest

  • A **Trade Asset Register Item** has several components:
    • Trade Strategy Model
      • Manages the actions to perform in a trade strategy (Enter, Exit, Position Size, Stop-Lost, etc.)
      • Has a reference to a Market Data Manager Object to get the required data
    • Trade Asset Investment Manager
      • Manages the funds allocated to the trade strategy
    • Broker
      • Open, closes, and updates trades (Simulated or Paper-Trading)

  • A **Trade Strategy Model** has different models controlling the different actions in a trade
    • A list of Enter Action models, and corresponding policy rules for the ensemble (required)
    • A list of Exit Action models, and corresponding policy rules for the ensemble (optional)
    • List of models for all other actions and their ensemble policies (optional)

  • A **Portfolio Register Item** defines a portfolio
    • It is an object that contains a list of Trade Asset Register Items and a Portfolio Investment Manager
    • The Portfolio Investment Manager, manages the funds for the entire portfolio, and re-balances the funds for the portfolio, if configured to do so, periodically.

Backtest' Types

There are different types of backtest supported, the following is a list of the different backtests types and their objectives:

**1. Backtest**

  • Executes a Trade Register Item or Portfolio Register Item in a test period
  • If any of the Trade Register Items contains at least one trade-action rule that is modeled via an AI Model, the modeled Fit date ranges must be specified (Training and Validation )
  • A Backtest generates a large set of performance statistics to analyze the trade strategy, and a set of trade performance plots (supported via the package: https://github.com/ranaroussi/quantstats )

**2. WFA Backtest**

  • Re-fit all AI models that a given trade strategy or portfolio depends during a backtest
  • The re-fit periodicity and size are configurable parameters, for ex:
    • Re-fit all AI Models every 3 months during a backtest, as the backtest progresses, it uses the updated fitted models for the action rules.

**3. Sliding Window WFA Backtest**

  • Executes a set of WFA-Backtests by sliding or extending the Training, Validation and Test Periods through time, and by also varying (optionally) the re-fit frequency per backtest.
  • Purpose of these set of backtest is to analyze the out-of-sample performance for trade strategies and/or portfolios through different market regimes.

**4. Grid-Search Backtest**

  • Run a set of backtests by varying a list of hyper-parameters for each Trade-Strategy or set of Trade Strategies.
  • Similar in spirit to https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html
  • The Grid-Search Backtest can be applied to a regular Backtest, a WFA-Backtest, or as an option in a Sliding-Window WFA Backtest; in the latter, the grid-search will be conducted prior to each sliding-window iteration.
  • The main purpose of this type of backtest, it is optimizing hyper parameters for one or more trade strategies in a backtest or per sliding-window shifting.

**5. Production-Sim Backtest**

  • The objective of this backtest is to allow the selection of a one or more trade strategies over time for trading. The trade strategies can vary over time, and have different hyper-parameters resulting from an optimization via the Grid-Search Backtest. Subsequently to selecting n number of Trade Strategies, evaluate them out-of-sample, and repeat this process many times through time using the Sliding Window WFA Backtest.
  • The main idea is that the trade strategies selected for trading can vary over time, as well as the hyper-parameters of the underlying models of the trade strategies, and the re-fit frequency. One must be careful to carry this process and selection process up to certain time, and only apply once out-of-sample, otherwise, one is adding bias to the selection process.

Graphical Representation

Examples

Summary

This section gives an overview of the current examples provided, and general instructions

  • The examples are categorized as follows:

    1. **Backtest**

    2. **WFA Backtest**

    3. **Sliding Window WFA Backtest**

    4. **Grid Backtest**

    5. **Production Sim Backtest**

    6. **Reports**

    7. **Other**

  • There is a common set of imports for all examples at the beginning that is required to be imported

  • The examples should be reviewed sequentially, as they get more complex and present more features as they progress. In addition, some examples refered to explanations and models from previous ones.

  • Every example is self-contained, this leads to a bit of duplication of code. However,in the interest of maximizing clarity this approached is used.

  • Every example has a detail description of the backtest at the start, the trade strategies in the backtest, the trade actions configured and their supporting models, their Fit Periods (only required if at least one AI model is present in the backtest), Test Period, etc.

  • Saving and Re-Storing any objects to a database is optional, in some examples is presented, but it is the same procedure for all examples/objects. In all cases, saving an object, cascades and saves all children objects, and retreiving an object, retrieves all children objects (lazy loading). Refer to SQLAlchemy for additional details.

  • The Trade Engine objects keep state associated with a given backtest, the only objects that should be shared between backtests are Market Data Objects, and Pipeline Data Managers, but they don't have to be.

Examples:

  • **Backtest**

    1. Nasdaq ETF - Yahoo Finance Market Data - SMA Trade Strategy

    • **Type :** Trade Strategy
    • **Models :** SMA
    • **Market Data Source:** Yahoo Finance
    • **Description:** One trade strategy: Nasdaq using Simple Moving Average(SMA) for entering/exiting a trade

    2. Cottons Futures - Quandal Market Data - SMA Trade Strategy

    • **Type :** Trade Strategy
    • **Models :** SMA
    • **Market Data Source:** Quandal
    • **Description:** One trade strategy: Cotton's Futures using Simple Moving Average(SMA) for entering/exiting a trade

    3. Nasdaq ETF - Yahoo Finance Market Data - LSTM Trade Strategy

    • **Type :** Trade Strategy
    • **Models :** LSTM
    • **Market Data Source:** Yahoo Finance
    • **Description:** One trade strategy: Nasdaq ETF using a LSTM-Model for entering/exiting a trade

    4. Portfolio A: Long and SMA Trade Strategies for US Indixes

    • **Type :** Portfolio
    • **Models :** SMA
    • **Market Data Source:** Yahoo Finance
    • **Description:** Portfolio with the following trade strategies:
        1. Three trade strategies: Nasdaq, S&P 500, and DOW Jones with buy-and-hold strategy
        1. Three trade strategies: Nasdaq, S&P 500, and DOW Jones using SMA

    5. Portfolio B: Long and AI LSTM based Strategies for US Indixes

    • **Type :** Portfolio
    • **Models :** LSTM
    • **Market Data Source:** Yahoo Finance
    • **Description:** Portfolio with the following trade strategies:
        1. Three trade strategies: Nasdaq, S&P 500, and DOW Jones with buy-and-hold strategy
        1. Three trade strategies: Nasdaq, S&P 500, and DOW Jones using LSTM AI Model

    6. Portfolio C: Long and Multiple Configured SMA Trade Strategies for US Indixes

    • **Type :** Portfolio
    • **Models :** Seven distinct SMA Models
    • **Market Data Source:** Yahoo Finance
    • **Description:** Portfolio with the following trade strategies:
        1. Three trade strategies: Nasdaq, S&P 500, and DOW Jones with buy-and-hold strategy
        1. Twenty-One trade strategies: Nasdaq, S&P 500, and DOW Jones using different SMA Models
        1. Three ensemble trade strategies based on all SMA models, one per US Index

    7. Portfolio D: Long and Multiple Configured LSTM Trade Strategies for US Indixes

    • **Type :** Portfolio
    • **Models :** Seven distinct LSTM Models
    • **Market Data Source:** Yahoo Finance
    • **Description:** Portfolio with the following trade strategies:
        1. Three trade strategies: Nasdaq, S&P 500, and DOW Jones with buy-and-hold strategy
        1. Twenty-One trade strategies: Nasdaq, S&P 500, and DOW Jones using different LSTM Models
        1. Three ensemble trade strategies based on all LSTM models, one per US Index

    8. Portfolio E: Long and Eleven Distinct Technical Analysis Based Trade Strategies for US Indixes

    • **Type :** Portfolio
    • **Models :** Elevent distinct Technical-Analysis (TA) Models
      • SMA, Bollinger Bands, MACD, RSI, Stochastic-RSI, ADX, KAMA, TSI, ForceIndex, MFI, SMA
    • **Market Data Source:** Yahoo Finance
    • **Description:** Portfolio with the following trade strategies:
        1. Three trade strategies: Nasdaq, S&P 500, and DOW Jones with buy-and-hold strategy
        1. Thirty-Three trade strategies: Nasdaq, S&P 500, and DOW Jones for each TA Model
        1. Three ensemble trade strategies based on all TA models, one per US Index

    9. Portfolio F: Long and Multiple Configured AI Modeled Trade Strategies for US Indixes

    • **Type :** Portfolio
    • **Models :** Eight distinct AI based models
      • GRU, LSTM, Conv1d-GRU, Conv1d-LSTM, Wavenet, Wavenet-GRU, GRU, Wavenet-LSTM
    • **Market Data Source:** Yahoo Finance
    • **Description:** Portfolio with the following trade strategies:
        1. Three trade strategies: Nasdaq, S&P 500, and DOW Jones with buy-and-hold strategy
        1. Twenty-Four trade strategies: Nasdaq, S&P 500, and DOW Jones for each AI trading model
        1. Three ensemble trade strategies based on all AI trading models, one per US Index

    10. Portfolio G: All Trade Strategies in Portfolio E and F

    • **Type :** Portfolio
    • **Models :** Eight distinct AI based models and Eleven TA based models
      • GRU, LSTM, Conv1d-GRU, Conv1d-LSTM, Wavenet, Wavenet-GRU, GRU, Wavenet-LSTM
      • SMA, Bollinger Bands, MACD, RSI, Stochastic-RSI, ADX, KAMA, TSI, ForceIndex, MFI, SMA
    • **Market Data Source:** Yahoo Finance
    • **Description:** Portfolio with the following trade strategies:
        1. Three trade strategies: Nasdaq, S&P 500, and DOW Jones with buy-and-hold strategy
        1. Fifty-Seven trade strategies: Nasdaq, S&P 500, and DOW Jones for each AI and TA trading model
        1. Three ensemble trade strategies based on all AI and TA trading models, one per US Index

    11. Portfolio H: Utilized Leveraged ETFs for Trading on The Model Trade-Asset

    • **Type :** Portfolio
      • This example shows the effect of creating a Trade Strategy with a given model for any trade asset, but actually, trading on an underlying leveraged ETF for that security
    • **Models :** Five distinct AI and TA based models
      • GRU, LSTM, Bollinger Bands, MACD, RSI
    • **Market Data Source:** Yahoo Finance
    • **Description:** Portfolio with the following trade strategies:
        1. Three trade strategies: Nasdaq, S&P 500, and DOW Jones with buy-and-hold strategy
        1. Five Trade Strategies are executed with ETF-on
        1. Five Trade Strategies are executed with ETF-off to show effect of ETF-on trading
        1. Three ensemble trade strategies based on all AI and TA trading models, one per US Index, for the ETF-on Trade Strategies
        1. Three ensemble trade strategies based on all AI and TA trading models, one per US Index, for the non-ETF Trade Strategies

    12. Portfolio I: Monthly Rebalance of Funds in a Portfolio

    • **Type :** Portfolio
    • **Models :** Same strategies as defined and explained in Portfolio C
    • **Market Data Source:** Yahoo Finance
    • **Description:**
      • Portfolio Investment Manager configured to balance funds monthly, using an equal weights policy

    13. Portfolio J: Trade Strategies with different Market Data Sources (Quandal, YahooFinance, User-Defined DataFrame)

    • **Type :** Portfolio
    • **Models :**
      • Multiple SMA Models, and LSTM, GRU, MACD, and RSI Models defined to use with each trading asset
    • **Market Data Source:** Yahoo Finance, Quandal, User-Defined DataFrame
    • **Description:**
      • This example shows how to configured a portfolio with trade strategies that depend on different market data sources.
      • Each trade strategy is associated with one Market Data Source, which may or may not be shared with other trade strategies.
      • This example also shows how to use any market data with the engine, provided it is in a Pandas DataFrame (details discussed in the example, regarding the format of the data frame)


  • **WFA Backtest**

    1. WFA-Backtest-1

    • **Type :** Portfolio
    • **Models :** Subset of the trade strategies in Portfolio D
    • **Market Data Source:** Yahoo Finance
    • **Description:**
      • Re-fit AI models every three months during the backtest
      • Don't anchored the training-set

    2. WFA-Backtest-2

    • **Type :** Portfolio
    • **Models :** Subset of the trade strategies in Portfolio G
    • **Market Data Source:** Yahoo Finance
    • **Description:**
      • Re-fit AI models every six months during the backtest
      • Anchored the training-set


  • **Slide Window WFA Backtest**

    1. SW-WFA-Backtest 1

    • **Type :** Portfolio
    • **Models :** Subset of the trade strategies in Portfolio D
    • **Market Data Source:** Yahoo Finance
    • **Description:**
      • Re-fit AI models every three months, then every six months within a backtest
      • Fixed Training and Validation periods
      • Training-set is not anchored during a backtest

    2. SW-WFA-Backtest 2

    • **Type :** Portfolio
    • **Models :** Subset of the trade strategies in Portfolio D
    • **Market Data Source:** Yahoo Finance
    • **Description:**
      • Re-fit AI models every six months within a backtest
      • Slide Datasets by one year increments for five consecutive years
      • Training-set is not anchored in outer slide window or during a backtest

    3. SW-WFA-Backtest 3

    • **Type :** Portfolio
    • **Models :** Subset of the trade strategies in Portfolio G
    • **Market Data Source:** Yahoo Finance
    • **Description:**
      • Re-fit AI trading models every 6 months within a backtest and anchored within the backtest
      • Fit datasets are anchored and duration increased by one year increments for five consecutive years
        • Every sliding window iteration, the training set duration is increased by 9 months and the validation set by 3 months, the test set is just shifted by one year.
      • Training-set is anchored in outer slide window and also anchored in the re-fitting process during a backtest


  • **Grid Backtest**

    To be added



  • **Production Sim Backtest**

    To be added



  • **Other**

    To be added

Backtest

In [4]:
# *** Imports required for running Trade Strategy examples

from trade_engine.model.TradeStrategyBaseModelPersist                import TradeStrategyBaseModelPersist
from trade_engine.model.TradeStrategyMarketDataMng                   import TradeStrategyMarketDataMng
from trade_engine.model.MarketDataPeriod                             import MarketDataPeriod
from trade_engine.ts_actions.generate.TradeStrategyActionGenerator   import TradeStrategyActionGenerator
from trade_engine.ts_actions.generate.TradeStrategyConfigData        import TradeStrategyConfigData
from trade_engine.investment_manager.TradingAssetInvMngBase          import TradingAssetInvMngBase
from trade_engine.registry.TradingAssetExecutionType                 import TradingAssetExecutionType
from trade_engine.registry.TradingAssetRegisterItem                  import TradingAssetRegisterItem
from trade_engine.broker.SimBrokerTrading                            import SimBrokerTrading
from trade_engine.execution.BacktestExecution                        import BacktestExecution
from trade_engine.dataset_def.DatasetDef                             import DatasetDef, DatasetType
from trade_engine.dataset_def.FitDatasetsDef                         import FitDatasetsDef
from trade_engine.reports.BacktestReports                            import BacktestReports

# *** Additional Imports required for running Portfolio examples

from tradeg.market_data.MarketData                                   import MarketData
from trade_engine.model.TALibPipelineBuilder                         import TALibPipelineBuilder
from trade_engine.model.TradeStrategyModelPipelineDataMng            import TradeStrategyModelPipelineDataMng
from trade_engine.enter_ts.TradeEnterClassicStrategy                 import TradeEnterClassicStrategy
from trade_engine.exit_ts.TradeExitClassicStrategy                   import TradeExitClassicStrategy
from trade_engine.model.classic.CacheTradingModel                    import CacheTradingModel
from trade_engine.model.classic.TradingRulesModel                    import TradingRulesModel
from trade_engine.model.classic.VotingTradingRulesModel              import VotingTradingRulesModel
from trade_engine.exit_ts.TradeExitStack                             import TradeExitStack
from trade_engine.enter_ts.TradeEnterStack                           import TradeEnterStack
from trade_engine.investment_manager.PortfolioInvMng                 import PortfolioInvMng
from trade_engine.investment_manager.PortfolioRebalanceFrequency     import PortfolioRebalanceFrequency
from trade_engine.registry.PortfolioRegisterItem                     import PortfolioRegisterItem
from trade_engine.model.ai.LSTM_Model                                import LSTM_Model
from trade_engine.model.ai.WaveNet_RNN_AI_TradingModel               import WaveNet_RNN_AI_TradingModel
from trade_engine.model.ai.WaveNet_RNN_AI_TradingModel               import WaveNet_RNN_AI_Trading_Rules
from trade_engine.model.ai.WaveNet_RNN_AI_PipelineBuilder            import WaveNet_RNN_AI_PipelineBuilder
from trade_engine.enter_ts.TradeEnterAIStrategy                      import TradeEnterAIStrategy
from trade_engine.exit_ts.TradeExitAIStrategy                        import TradeExitAIStrategy
from trade_engine.ts_actions.policy.TradeEnterSetPolicy  import TradeEnterSetPolicy, TradeEnterSetVotingPolicy
from trade_engine.ts_actions.policy.TradeEnterPolicy     import TradeEnterPolicy
from trade_engine.ts_actions.policy.TradeExitSetPolicy   import TradeExitSetPolicy, TradeExitSetVotingPolicy
from trade_engine.ts_actions.policy.TradeExitPolicy      import TradeExitPolicy

# *** Additional Imports required for running WFA Backtest and Slide Win WFA Backtest

from trade_engine.execution.BacktestExecutionWFA             import BacktestExecutionWFA, WFASlideWindowPeriod
from trade_engine.execution.BacktestExecutionSlideWindowWFA  import BacktestExecutionSlideWindowWFA
from trade_engine.execution.BacktestExecutionSlideWindowWFA  import WFASlideWinScenarioFixDatasets
from trade_engine.execution.BacktestExecutionSlideWindowWFA  import WFASlideWinScenarioSlidingDatasets
from trade_engine.execution.BacktestExecutionSlideWindowWFA  import WFASlideWinScenarioAnchoredSlidingDatasets

Trade Strategies

Nasdaq ETF - Yahoo Finance Market Data - SMA Trade Strategy

  • SMA Trade Strategy for Nasdaq ETF

    Description:

      1. $1.0M Budget
      2. 100% capital invested
    
    

    Trade Strategies:

      1. One trade strategy: Nasdaq using Simple Moving Average(SMA) for entering/exiting a trade
    
    

    Backtest:

      1. Type: regular
      2. Test Period: 
          1. Begin Date = 2001-01-01 
          2. End Date   = 2005-12-31 
Trade Asset
In [5]:
trade_assets   = [ "^IXIC" ]
Market Data Manager

Market Data Manager configured to use yahoo-finance for obtaining market data

The following TradeStrategyMarketDataMng object will do the following:

1. Download market data for: 
    [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
2. Used yahoo-finance as the market provider
3. Save the downloaded data in the directory and file specified by the arguments:
   1. dirPathMarketData
   2. fileNameMarketData
4. It will request the market data provider to get data from "beg_date_str" to "end_date_str"
5. If end_date_str is not defined (as the case below), all data available from the begin date is 
   requested.
6. Interval is set to "1d", this parameter is market data provider specific, see Yahoo-Finance, 
   Quandal for what options they support
7. The **Adj Close** column is configured as the default price column 
8. Note that even so leveraged ETFs are requested from 2000-01-01 to the present, the data 
   actually returned for these stock symbols by Yahoo-Finance doesn't start until 2011.
   The behavior is market data provider specific
In [6]:
dirPathMarketData = '/Users/gustavozambrana/Google Drive/Python/Projects/Trade_Engine/Data/US_Market_Indixes'

supportedTradeAssets   = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str           = "2000-01-01"
end_date_str           = None

ts_marketdat_mng = TradeStrategyMarketDataMng(\
        marketDataProviderName = "yahoofinance",
        supportedTradeAssets   = supportedTradeAssets,
        stock_price_col_name   = "Adj Close",
        fileNameMarketData     = "US_Indixes_And_ETFs_MrkData",
        dirPathMarketData      = dirPathMarketData,
        beg_date_str           = beg_date_str,
        end_date_str           = end_date_str,
        interval               = "1d"  ) 
2021-11-02 09:24:16,038 [INFO] root: Found previous Market data previously loaded to specified file and dir.
In [7]:
ts_marketdat_mng.marketDataObj.getDataFrame()
Out[7]:
Index Adj Close Close High Low Open Volume
Date
2000-01-03 ^DJI 11357.509766 11357.509766 11522.009766 11305.690430 11501.849609 169750000
2000-01-03 ^GSPC 1455.219971 1455.219971 1478.000000 1438.359985 1469.250000 931800000
2000-01-03 ^IXIC 4131.149902 4131.149902 4192.189941 3989.709961 4186.189941 1510070000
2000-01-04 ^DJI 10997.929688 10997.929688 11350.059570 10986.450195 11349.750000 178420000
2000-01-04 ^GSPC 1399.420044 1399.420044 1455.219971 1397.430054 1455.219971 1009000000
... ... ... ... ... ... ... ...
2021-09-20 TQQQ 133.490005 133.490005 137.460007 128.000000 135.419998 60721113
2021-09-20 UDOW 69.760002 69.760002 71.459999 67.519997 70.220001 6439708
2021-09-20 ^DJI 33970.468750 33970.468750 34459.718750 33613.031250 34459.718750 441645657
2021-09-20 ^GSPC 4357.729980 4357.729980 4402.950195 4305.910156 4402.950195 2598257000
2021-09-20 ^IXIC 14713.903320 14713.903320 14841.815430 14530.073242 14758.099609 4350941000

34549 rows × 7 columns

Simulation Broker
In [8]:
brokerTradingObj = SimBrokerTrading()
Trade Strategy, Trade Investment Manager, and Trade Asset Register Item
In [9]:
tsConfDat = TradeStrategyConfigData()

# SMA JSON Configuration
#
# Model Configuration:
#                win_fast   : fast moving average
#                win_slow   : slow moving average
# Signals to enter and exit a trade based on the fast ma crossing the slow ma

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 20, 'win_slow' : 100 } },
                            } } )
In [10]:
tsActionGen = TradeStrategyActionGenerator()
trade_asset = trade_assets[0]
    
# *** Trade Strategy Entry and Exit Rules based on SMA 

ts_unique_name = "ts_sma"
trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                         ts_marketdat_mng  = ts_marketdat_mng, 
                                         test_trade_asset  = trade_asset, 
                                         dirPathMarketData = dirPathMarketData,
                                         actionData        = tsConfDat )
# *** Trade Strategy Model

ts_model = TradeStrategyBaseModelPersist(\
                trade_asset               = trade_asset,
                ts_marketdat_mng          = ts_marketdat_mng,
                ts_enter                  = trade_enter_set,
                ts_exit                   = trade_exit_set,                       
                model_type                = ts_unique_name,
                model_version             = "1.0",
                market_data_period        = MarketDataPeriod.Day,
            ) 

# *** Trade Strategy Investment Manager 

taInvMng = TradingAssetInvMngBase(\
                                trade_asset                = trade_asset,
                                minPeriodsBetweenTrades    = 1,
                                initInvestment             = 1000000.0, 
                                capPercentToInvestPerTrade = 100.0,      #invest all funds avail in each trade
                                minInvestPercent           = 5.0,        
                                min_account_balance        = 1000.0 )

# *** Trade Register Item
# *** This object has all configuration defined to execute a given trade strategy,
# *** It can be executed individually in backtest or as part of a portfolio

ta_registered_item = TradingAssetRegisterItem(\
        trade_name                    = "{0}_{1}".format(ts_unique_name, trade_asset), 
        ts_model                      = ts_model,
        tradingExecutionType          = TradingAssetExecutionType.Simulation,
        tradingBrokerObj              = brokerTradingObj,
        tradingAssetInvMngObj         = taInvMng )  
Display Entry Rules Generated SMA Signals
In [11]:
trade_enter_set.tsEntries[0].ts_model_pipline_mng.\
     getAllModelDataPipelineDataForStockSymbol(stockSymbol = "^IXIC" )
Out[11]:
Index Adj Close Close High Low Open Volume sma_fast sma_slow sma_fast_gt_sma_slow sma_fast_lt_sma_slow
Date
2000-05-24 ^IXIC 3270.610107 3270.610107 3276.189941 3042.659912 3155.139893 2087980000 3599.450500 4167.194609 0 1
2000-05-25 ^IXIC 3205.350098 3205.350098 3365.840088 3194.590088 3308.510010 1561840000 3571.016504 4157.936611 0 1
2000-05-26 ^IXIC 3205.110107 3205.110107 3256.629883 3150.780029 3215.280029 1069440000 3538.239014 4150.970813 0 1
2000-05-30 ^IXIC 3459.479980 3459.479980 3460.239990 3286.540039 3286.540039 1457360000 3513.309009 4146.790212 0 1
2000-05-31 ^IXIC 3400.909912 3400.909912 3501.510010 3399.620117 3428.250000 1533730000 3494.082007 4143.528013 0 1
... ... ... ... ... ... ... ... ... ... ... ...
2021-09-14 ^IXIC 15037.759766 15037.759766 15181.190430 15008.299805 15168.450195 4571950000 15060.770947 14363.204189 1 0
2021-09-15 ^IXIC 15161.530273 15161.530273 15174.379883 14984.679688 15071.339844 4446270000 15086.038477 14374.651396 1 0
2021-09-16 ^IXIC 15181.919922 15181.919922 15205.500000 15047.139648 15120.089844 3681700000 15118.838965 14385.082793 1 0
2021-09-17 ^IXIC 15043.969727 15043.969727 15166.559570 14998.730469 15163.360352 6682650000 15143.947949 14394.620293 1 0
2021-09-20 ^IXIC 14713.903320 14713.903320 14841.815430 14530.073242 14758.099609 4350941000 15143.910107 14401.249023 1 0

5365 rows × 11 columns

Execute Backtest
In [12]:
tsExecuteEngine = BacktestExecution( \
                    name = "Backtest for Nasdaq ETF - SMA Trade Strategy",
                    timePeriod = DatasetDef(datasetType = DatasetType.Testing,
                                            strBegDate = "2001-01-01", 
                                            strEndDate = "2005-12-31" ),
                    trade_asset_registered_item = ta_registered_item )
In [ ]:
tsExecuteEngine.evaluate()
Backtest Metrics
Execution & Investment Metrics
In [14]:
tsExecuteEngine.getExecutionMetrics()
Out[14]:
TA_Reg_Name TA_Reg_Id Inv_Mng_Id Inv_Mng_Parent_Id Is_Portfolio Num_Trades_Executing Num_Trades_Completed Init_Capital Final_Capital Final_Inv_Capital Cum_Return Backtest_Status
0 ts_sma_^IXIC None None None No 0 22 1000000.0 837290.360474 0.0 -0.16271 Completed
Performance Metrics
In [15]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ]
Out[15]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
0 ts_sma_^IXIC No ts_sma ^IXIC 2001-01-03 2005-12-30 1.0 -0.16 -0.03 -0.01 -0.48 0.08 -0.14
In [16]:
tsExecuteEngine.getSummaryMetrics().T.head(60)
Out[16]:
0
ta_reg_item_name ts_sma_^IXIC
ta_reg_item_id None
is_portfolio No
model_type ts_sma
trade_asset ^IXIC
test_period_len_days 1825
tr_period_len_days 0
val_period_len_days 0
index Strategy
Start Period 2001-01-03
End Period 2005-12-30
Risk-Free Rate 0.0
Time in Market 1.0
Cumulative Return -0.16
CAGR% -0.03
Sharpe -0.01
Sortino -0.01
Sortino/√2 -0.01
Max Drawdown -0.48
Longest DD Days 1730
Volatility (ann.) 0.26
Calmar -0.07
Skew -0.42
Kurtosis 6.01
Expected Daily % -0.0
Expected Monthly % -0.0
Expected Yearly % -0.03
Kelly Criterion -0.0
Risk of Ruin 0.0
Daily Value-at-Risk -0.03
Expected Shortfall (cVaR) -0.03
Gain/Pain Ratio -0.0
Gain/Pain (1M) -0.01
Payoff Ratio 1.03
Profit Factor 1.0
Common Sense Ratio 0.95
CPC Index 0.51
Tail Ratio 0.95
Outlier Win Ratio 3.59
Outlier Loss Ratio 3.5
MTD -0.01
3M -0.08
6M -0.06
YTD -0.13
1Y -0.13
3Y (ann.) -0.02
5Y (ann.) -0.03
10Y (ann.) -0.03
All-time (ann.) -0.03
Best Day 0.08
Worst Day -0.14
Best Month 0.34
Worst Month -0.21
Best Year 0.27
Worst Year -0.15
Avg. Drawdown -0.1
Avg. Drawdown Days 199
Recovery Factor -0.34
Ulcer Index 1.02
Avg. Up Month 0.06
Persist Backtest to DB (optional )
In [ ]:
session.add( tsExecuteEngine )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst)
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")

Cottons Futures - Quandal Market Data - SMA Trade Strategy

  • SMA Trade Strategy for Cottons Future

    Description:

      1. $1.0M Budget
      2. 100% capital invested
    
    

    Trade Strategies:

      1. One trade strategy: Cotton's Futures using Simple Moving Average(SMA) for entering/exiting a trade
    
    

    Backtest:

      1. Type: regular
      2. Test Period: 
          1. Begin Date = 2002-01-01 
          2. End Date   = 2005-12-31 
Market Data Manager
Trade Assets - Quandal

Download the following data from Quandal:

  1. CHRIS/ICE_CT1

    Where CHRIS is the Quandal Data Provider, and the name after the / is the Futures symbol.

    The format of the JSON to download from Quandal is:

    { quandal-path :

       [ description of data, 
         [ columns to extract from the returned Quandal DataFrame ], 
         { "Quandal_Column" : "Rename Quandal Column" } 
       ]
    

    }

Note:

1. The nested dictionary to rename the original downloaded Quandal data, it is provided since Quandal does
   not have standard output column names.  
       - Futures data from different data sources might have different returned column names for the same
         state, that is "Close" vs. "close", etc.
       - For sharing the same market data manager object it is recommended to rename the columns to have 
         standard names, and match the ones provided by Yahoo Finance

2. Yahoo Finance returns standard equity column names

3. All implemented AI and Technical Models used standard column names (same as Yahoo Finance)
   Columns: Adj Close, Close, Open, High, Low, Volume
   Index: Datetime

4. In order to use the implemented models the Quandal Market Data or any Custom Market Data must have
   similar named columns, or the user can implement his own models and use whatever column names he/she
   prefers.

5. In this example, the Quandal data source does not provide all standard column names, only open,
   which is re-named to 'Adj Close'.  Therefore only some of the built models will be available,
   as they required High, Low, such as Bollinger Bands
In [17]:
indexQuantCodeMap = { 
       "CHRIS/ICE_CT1" : ["Cotton",   ["Open", "Volume"],  { "Open" : "Adj Close" } ] 
}
In [18]:
dirPathMarketDataQuandl = '/Users/gustavozambrana/Google Drive/Python/Projects/Trade_Engine/Data/TSMarketDat'

beg_date_for_feature_creation = "2000-10-01"
beg_date_str                  = "2001-01-01"
end_date_str                  = "2010-12-31"

q_stock_index_list = list ( indexQuantCodeMap.keys()  )

ts_marketdat_mng_quandal = TradeStrategyMarketDataMng(\
        marketDataProviderName = "quandl",
        supportedTradeAssets   = q_stock_index_list,   
        stock_price_col_name   = "Adj Close",
        fileNameMarketData     = "Quandl_Test_1",
        dirPathMarketData      = dirPathMarketDataQuandl,
        beg_date_str           = beg_date_for_feature_creation,
        end_date_str           = end_date_str,
        interval               = "1d" ,
        updateDataPassEndDate  = False,
        forceCreateMarketData  = False,
        indexQuantCodeMap      = indexQuantCodeMap     # required for quandl market data provider, defined above
        ) 
2021-11-02 09:26:33,287 [INFO] root: Found previous Market data previously loaded to specified file and dir.
In [19]:
ts_marketdat_mng_quandal.marketDataObj.getDataFrame()
Out[19]:
Index Index_Name Provider Adj Close Volume
Date
2000-10-02 CHRIS/ICE_CT1 Cotton Quandl 62.17 40.0
2000-10-03 CHRIS/ICE_CT1 Cotton Quandl 63.40 120.0
2000-10-04 CHRIS/ICE_CT1 Cotton Quandl 63.70 37.0
2000-10-05 CHRIS/ICE_CT1 Cotton Quandl 63.80 21.0
2000-10-06 CHRIS/ICE_CT1 Cotton Quandl 63.95 84.0
... ... ... ... ... ...
2010-12-27 CHRIS/ICE_CT1 Cotton Quandl 147.12 7893.0
2010-12-28 CHRIS/ICE_CT1 Cotton Quandl 146.31 4413.0
2010-12-29 CHRIS/ICE_CT1 Cotton Quandl 143.86 6900.0
2010-12-30 CHRIS/ICE_CT1 Cotton Quandl 140.00 10309.0
2010-12-31 CHRIS/ICE_CT1 Cotton Quandl 144.00 5421.0

2401 rows × 5 columns

Simulation Broker
In [20]:
brokerTradingObj = SimBrokerTrading()
Trade Strategy, Trade Investment Manager, and Trade Asset Register Item
In [21]:
tsConfDat = TradeStrategyConfigData()

# SMA JSON Configuration

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 20, 'win_slow' : 100 } },
                            } } )
In [22]:
tsActionGen = TradeStrategyActionGenerator()
trade_asset = "CHRIS/ICE_CT1"
    
# *** Trade Strategy Entry and Exit Rules based on SMA 

ts_unique_name = "ts_sma"
trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                         ts_marketdat_mng  = ts_marketdat_mng_quandal, 
                                         test_trade_asset  = trade_asset, 
                                         dirPathMarketData = dirPathMarketData,
                                         actionData        = tsConfDat )
# *** Trade Strategy Model

ts_model = TradeStrategyBaseModelPersist(\
                trade_asset               = trade_asset,
                ts_marketdat_mng          = ts_marketdat_mng_quandal,
                ts_enter                  = trade_enter_set,
                ts_exit                   = trade_exit_set,                       
                model_type                = ts_unique_name,
                model_version             = "1.0",
                market_data_period        = MarketDataPeriod.Day,
            ) 

# *** Trade Strategy Investment Manager 

taInvMng = TradingAssetInvMngBase(\
                                trade_asset                = trade_asset,
                                minPeriodsBetweenTrades    = 1,
                                initInvestment             = 1000000.0, 
                                capPercentToInvestPerTrade = 100.0,      #invest all funds avail in each trade
                                minInvestPercent           = 5.0,        
                                min_account_balance        = 1000.0 )

# *** Trade Register Item
# *** This object has all configuration defined to execute a given trade strategy,
# *** It can be executed individually in backtest or as part of a portfolio

ta_registered_item = TradingAssetRegisterItem(\
        trade_name                    = "{0}_{1}".format(ts_unique_name, trade_asset), 
        ts_model                      = ts_model,
        tradingExecutionType          = TradingAssetExecutionType.Simulation,
        tradingBrokerObj              = brokerTradingObj,
        tradingAssetInvMngObj         = taInvMng )  
Display Entry Rules Generated SMA Signals
In [23]:
trade_enter_set.tsEntries[0].ts_model_pipline_mng.\
     getAllModelDataPipelineDataForStockSymbol(stockSymbol = trade_asset )
Out[23]:
Index Index_Name Provider Adj Close Volume sma_fast sma_slow sma_fast_gt_sma_slow sma_fast_lt_sma_slow
Date
2001-02-26 CHRIS/ICE_CT1 Cotton Quandl 55.25 49.0 59.3340 62.6098 0 1
2001-02-27 CHRIS/ICE_CT1 Cotton Quandl 53.50 176.0 58.9390 62.5231 0 1
2001-02-28 CHRIS/ICE_CT1 Cotton Quandl 51.95 166.0 58.4860 62.4086 0 1
2001-03-01 CHRIS/ICE_CT1 Cotton Quandl 53.10 46.0 58.0310 62.3026 0 1
2001-03-02 CHRIS/ICE_CT1 Cotton Quandl 53.75 83.0 57.6685 62.2021 0 1
... ... ... ... ... ... ... ... ... ...
2010-12-27 CHRIS/ICE_CT1 Cotton Quandl 147.12 7893.0 136.7070 108.9030 1 0
2010-12-28 CHRIS/ICE_CT1 Cotton Quandl 146.31 4413.0 137.5775 109.5818 1 0
2010-12-29 CHRIS/ICE_CT1 Cotton Quandl 143.86 6900.0 138.0755 110.2359 1 0
2010-12-30 CHRIS/ICE_CT1 Cotton Quandl 140.00 10309.0 138.7005 110.8444 1 0
2010-12-31 CHRIS/ICE_CT1 Cotton Quandl 144.00 5421.0 139.8280 111.4864 1 0

2302 rows × 9 columns

Execute Backtest
In [24]:
tsExecuteEngine = BacktestExecution( \
                    name = "Backtest for Cottons Futures - SMA Trade Strategy",
                    timePeriod = DatasetDef(datasetType = DatasetType.Testing,
                                            strBegDate = "2002-01-01", 
                                            strEndDate = "2005-12-31" ),
                    trade_asset_registered_item = ta_registered_item )
In [ ]:
tsExecuteEngine.evaluate()
Backtest Metrics
Execution & Investment Metrics
In [26]:
tsExecuteEngine.getExecutionMetrics()
Out[26]:
TA_Reg_Name TA_Reg_Id Inv_Mng_Id Inv_Mng_Parent_Id Is_Portfolio Num_Trades_Executing Num_Trades_Completed Init_Capital Final_Capital Final_Inv_Capital Cum_Return Backtest_Status
0 ts_sma_CHRIS/ICE_CT1 None None None No 0 13 1000000.0 942553.57 0.0 -0.057446 Completed
Performance Metrics
In [27]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ]
Out[27]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
0 ts_sma_CHRIS/ICE_CT1 No ts_sma CHRIS/ICE_CT1 2002-01-03 2005-12-30 0.98 -0.06 -0.01 0.12 -0.38 0.19 -0.09
In [28]:
tsExecuteEngine.getSummaryMetrics().T.head(60)
Out[28]:
0
ta_reg_item_name ts_sma_CHRIS/ICE_CT1
ta_reg_item_id None
is_portfolio No
model_type ts_sma
trade_asset CHRIS/ICE_CT1
test_period_len_days 1460
tr_period_len_days 0
val_period_len_days 0
index Strategy
Start Period 2002-01-03
End Period 2005-12-30
Risk-Free Rate 0.0
Time in Market 0.98
Cumulative Return -0.06
CAGR% -0.01
Sharpe 0.12
Sortino 0.19
Sortino/√2 0.13
Max Drawdown -0.38
Longest DD Days 571
Volatility (ann.) 0.34
Calmar -0.04
Skew 1.23
Kurtosis 10.68
Expected Daily % -0.0
Expected Monthly % -0.0
Expected Yearly % -0.01
Kelly Criterion 0.01
Risk of Ruin 0.0
Daily Value-at-Risk -0.03
Expected Shortfall (cVaR) -0.03
Gain/Pain Ratio 0.02
Gain/Pain (1M) 0.09
Payoff Ratio 1.08
Profit Factor 1.02
Common Sense Ratio 1.06
CPC Index 0.54
Tail Ratio 1.04
Outlier Win Ratio 3.77
Outlier Loss Ratio 3.61
MTD -0.07
3M -0.1
6M -0.18
YTD -0.31
1Y -0.3
3Y (ann.) -0.0
5Y (ann.) -0.01
10Y (ann.) -0.01
All-time (ann.) -0.01
Best Day 0.19
Worst Day -0.09
Best Month 0.21
Worst Month -0.2
Best Year 0.22
Worst Year -0.31
Avg. Drawdown -0.09
Avg. Drawdown Days 94
Recovery Factor -0.15
Ulcer Index 1.02
Avg. Up Month 0.08
Persist Backtest to DB (optional )
In [ ]:
session.add( tsExecuteEngine )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst)
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")

Nasdaq ETF - Yahoo Finance Market Data - LSTM Trade Strategy

  • LSTM Trade Strategy for Nasdaq ETF

    Description:

      1. $1.0M Budget
      2. 100% capital invested
    
    

    Trade Strategies:

      1. One trade strategy: Nasdaq using a LSTM-Model for entering/exiting a trade
    
    

    Backtest:

      1. Type: regular
      2. AI Models Fit Date Ranges
          1. Training Period: 
              1. Begin Date = 2001-01-01 
              2. End Date   = 2005-12-31  
          2. Validation Period: 
              1. Begin Date = 2006-01-01 
              2. End Date   = 2007-06-30   
      4. Test Period: 
          1. Begin Date = 2008-01-01 
          2. End Date   = 2008-12-31 
Trade Asset
In [29]:
trade_assets   = [ "^IXIC" ]
Market Data Manager

Market Data Manager configured to use yahoo-finance for obtaining market data

The following TradeStrategyMarketDataMng object will do the following:

1. Download market data for: 
    [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
2. Used yahoo-finance as the market provider
3. Save the downloaded data in the directory and file specified by the arguments:
   1. dirPathMarketData
   2. fileNameMarketData
4. It will request the market data provider to get data from "beg_date_str" to "end_date_str"
5. If end_date_str is not defined (as the case below), all data available from the begin date is 
   requested.
6. Interval is set to "1d", this parameter is market data provider specific, see Yahoo-Finance, 
   Quandal for what options they support
7. The **Adj Close** column is configured as the default price column 
8. Note that even so leveraged ETFs are requested from 2000-01-01 to the present, the data 
   actually returned for these stock symbols by Yahoo-Finance doesn't start until 2011.
   The behavior is market data provider specific
In [30]:
dirPathMarketData = '/Users/gustavozambrana/Google Drive/Python/Projects/Trade_Engine/Data/US_Market_Indixes'

supportedTradeAssets   = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str           = "2000-01-01"
end_date_str           = None

ts_marketdat_mng = TradeStrategyMarketDataMng(\
        marketDataProviderName = "yahoofinance",
        supportedTradeAssets   = supportedTradeAssets,
        stock_price_col_name   = "Adj Close",
        fileNameMarketData     = "US_Indixes_And_ETFs_MrkData",
        dirPathMarketData      = dirPathMarketData,
        beg_date_str           = beg_date_str,
        end_date_str           = end_date_str,
        interval               = "1d"  ) 
2021-11-02 09:29:25,029 [INFO] root: Found previous Market data previously loaded to specified file and dir.
In [31]:
ts_marketdat_mng.marketDataObj.getDataFrame()
Out[31]:
Index Adj Close Close High Low Open Volume
Date
2000-01-03 ^DJI 11357.509766 11357.509766 11522.009766 11305.690430 11501.849609 169750000
2000-01-03 ^GSPC 1455.219971 1455.219971 1478.000000 1438.359985 1469.250000 931800000
2000-01-03 ^IXIC 4131.149902 4131.149902 4192.189941 3989.709961 4186.189941 1510070000
2000-01-04 ^DJI 10997.929688 10997.929688 11350.059570 10986.450195 11349.750000 178420000
2000-01-04 ^GSPC 1399.420044 1399.420044 1455.219971 1397.430054 1455.219971 1009000000
... ... ... ... ... ... ... ...
2021-09-20 TQQQ 133.490005 133.490005 137.460007 128.000000 135.419998 60721113
2021-09-20 UDOW 69.760002 69.760002 71.459999 67.519997 70.220001 6439708
2021-09-20 ^DJI 33970.468750 33970.468750 34459.718750 33613.031250 34459.718750 441645657
2021-09-20 ^GSPC 4357.729980 4357.729980 4402.950195 4305.910156 4402.950195 2598257000
2021-09-20 ^IXIC 14713.903320 14713.903320 14841.815430 14530.073242 14758.099609 4350941000

34549 rows × 7 columns

Simulation Broker
In [32]:
brokerTradingObj = SimBrokerTrading()
Trade Strategy, Trade Investment Manager, and Trade Asset Register Item
In [33]:
tsConfDat = TradeStrategyConfigData()

# LSTM JSON Configuration
#
# Model configuration:
#     Simple LSTM MOdel with two layers
#     n_steps            : length of time series
#     no_neurons_lay1    : layer 1 neurons
#     no_neurons_lay2    : layer 2 neurons
#     pred_ahead_periods : Number of prediction points ahead
#     epochs             : Number of epochs
#     ext_trade_dyn      : Extend an existent trade dymically based on current period predictions
#     re_eval_exit_dyn   : Re-evaluate exiting a trade dynamically based on current period predictions
#     entry_policy_args  :
#                          lastn_match        : Enter a trade if the last n predictions matched
#                          cross_enter_signal : Enter a trade if the there is a cross-over signal, 
#                                               from buy-to-sell, sell-to-buy
#     exit_policy_args   :
#                          lastn_match        : Exit a trade if the last n predictions matched


tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_lstm",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 3,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'         : 20 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 1, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },
                             },
                    }  )
In [34]:
tsActionGen = TradeStrategyActionGenerator()
trade_asset = "^IXIC"
    
# *** Trade Strategy Entry and Exit Rules based on SMA 

ts_unique_name = "ts_lstm"
trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                         ts_marketdat_mng  = ts_marketdat_mng, 
                                         test_trade_asset  = trade_asset, 
                                         dirPathMarketData = dirPathMarketData,
                                         actionData        = tsConfDat )
# *** Trade Strategy Model

ts_model = TradeStrategyBaseModelPersist(\
                trade_asset               = trade_asset,
                ts_marketdat_mng          = ts_marketdat_mng,
                ts_enter                  = trade_enter_set,
                ts_exit                   = trade_exit_set,                       
                model_type                = ts_unique_name,
                model_version             = "1.0",
                market_data_period        = MarketDataPeriod.Day,
            ) 

# *** Trade Strategy Investment Manager 

taInvMng = TradingAssetInvMngBase(\
                                trade_asset                = trade_asset,
                                minPeriodsBetweenTrades    = 1,
                                initInvestment             = 1000000.0, 
                                capPercentToInvestPerTrade = 100.0,      #invest all funds avail in each trade
                                minInvestPercent           = 5.0,        
                                min_account_balance        = 1000.0 )

# *** Trade Register Item
# *** This object has all configuration defined to execute a given trade strategy,
# *** It can be executed individually in backtest or as part of a portfolio

ta_registered_item = TradingAssetRegisterItem(\
        trade_name                    = "{0}_{1}".format(ts_unique_name, trade_asset), 
        ts_model                      = ts_model,
        tradingExecutionType          = TradingAssetExecutionType.Simulation,
        tradingBrokerObj              = brokerTradingObj,
        tradingAssetInvMngObj         = taInvMng )  
Display Pipeline Data for LSTM Model
In [35]:
# Pipeline just normalizes the data
trade_enter_set.tsEntries[0].ts_model_pipline_mng.\
     getAllModelDataPipelineDataForStockSymbol(stockSymbol = "^IXIC" )
Out[35]:
Adj Close Close High Low Open Volume Index
Date
2000-01-03 0.211570 0.211570 0.214213 0.202407 0.215259 0.124230 ^IXIC
2000-01-04 0.195479 0.195479 0.205877 0.195980 0.203604 0.124392 ^IXIC
2000-01-05 0.193786 0.193786 0.195431 0.184504 0.191987 0.144828 ^IXIC
2000-01-06 0.183238 0.183238 0.191544 0.183152 0.190591 0.132287 ^IXIC
2000-01-07 0.194142 0.194142 0.192519 0.182834 0.181941 0.135630 ^IXIC
... ... ... ... ... ... ... ...
2021-09-14 0.976398 0.976398 0.984423 0.976467 0.985446 0.403784 ^IXIC
2021-09-15 0.985077 0.985077 0.983945 0.974808 0.978636 0.392309 ^IXIC
2021-09-16 0.986507 0.986507 0.986127 0.979196 0.982054 0.322503 ^IXIC
2021-09-17 0.976833 0.976833 0.983397 0.975795 0.985089 0.596493 ^IXIC
2021-09-20 0.953687 0.953687 0.960636 0.942872 0.956668 0.383605 ^IXIC

5464 rows × 7 columns

Training, Validation and Test Periods for Backtest

In Order to backtest a trade strategy or portfolio that has AI models, the following data is required:

  1. Training Date Range

    1. Date range that will be used to train the AI models in the backtest
  2. Validation Date Range

    1. Date range that twill be used to validate the AI models, should not overlapped with the training date range
  3. Test Period Date Range

    1. This is the out-sample date range, which corresponds to the date range of the backtest

Date Ranges are defined with a DatasetDef object, and have the following parameters:

  1. strBegDateAIModels : Date to begin training or validation of an AI model
  2. strBegDate : Date to begin the backtest
  3. strEndDate : Date to end training, validation and Backtest

Note:

  1. The param strBegDateAIModels can be defined as the same date as strBegDate, that is the default, if not defined.
  2. The critical aspect of using this parameter is in the backtest. Some AI Models, such as time series, others using moving averages over many periods, create params with no predicting data for those initial dates. Thus, in order to ensure the backtest starts on the actual date specified, the strBegDateAIModels should be defined as an earlier date, and it should not overlapped with the validation period end-date to avoid any chance of bias by picking at the validation data.
In [36]:
training_period = DatasetDef(datasetType = DatasetType.Training,
                             strBegDateAIModels = "2000-07-01",
                             strBegDate         = "2001-01-01",
                             strEndDate         = "2005-12-31" )

validation_period = DatasetDef(datasetType = DatasetType.Validation,
                               strBegDateAIModels = "2005-07-01",
                               strBegDate         = "2006-01-01",
                               strEndDate         = "2007-06-30" )

testing_period = DatasetDef(datasetType = DatasetType.Testing,
                               strBegDateAIModels = "2007-07-01",
                               strBegDate         = "2008-01-01",
                               strEndDate         = "2008-12-31" )

fit_datasets = FitDatasetsDef( trainingDataset    = training_period,
                               validationDataset  = validation_period )
Execute Backtest
In [37]:
tsExecuteEngine = BacktestExecution( \
                    name = "Backtest for Nasdaq-ETF LSTM based Trade Strategy",
                    timePeriod  = testing_period,
                    fitDatasets = fit_datasets,
                    trade_asset_registered_item = ta_registered_item )
In [ ]:
tsExecuteEngine.evaluate()
Backtest Metrics
Execution & Investment Metrics
In [39]:
tsExecuteEngine.getExecutionMetrics()
Out[39]:
TA_Reg_Name TA_Reg_Id Inv_Mng_Id Inv_Mng_Parent_Id Is_Portfolio Num_Trades_Executing Num_Trades_Completed Init_Capital Final_Capital Final_Inv_Capital Cum_Return Backtest_Status
0 ts_lstm_^IXIC None None None No 0 56 1000000.0 2.746124e+06 0.0 1.746124 Completed
Performance Metrics
In [40]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ]
Out[40]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
0 ts_lstm_^IXIC No ts_lstm ^IXIC 2008-01-03 2008-12-31 1.0 1.75 1.76 2.67 -0.23 0.12 -0.07
In [41]:
tsExecuteEngine.getSummaryMetrics().T.head(60)
Out[41]:
0
ta_reg_item_name ts_lstm_^IXIC
ta_reg_item_id None
is_portfolio No
model_type ts_lstm
trade_asset ^IXIC
test_period_len_days 365
tr_period_len_days 1825
val_period_len_days 545
index Strategy
Start Period 2008-01-03
End Period 2008-12-31
Risk-Free Rate 0.0
Time in Market 1.0
Cumulative Return 1.75
CAGR% 1.76
Sharpe 2.67
Sortino 4.81
Sortino/√2 3.4
Max Drawdown -0.23
Longest DD Days 54
Volatility (ann.) 0.41
Calmar 7.58
Skew 0.81
Kurtosis 2.75
Expected Daily % 0.0
Expected Monthly % 0.09
Expected Yearly % 1.75
Kelly Criterion 0.22
Risk of Ruin 0.0
Daily Value-at-Risk -0.04
Expected Shortfall (cVaR) -0.04
Gain/Pain Ratio 0.62
Gain/Pain (1M) 6.99
Payoff Ratio 1.22
Profit Factor 1.62
Common Sense Ratio 2.3
CPC Index 1.13
Tail Ratio 1.42
Outlier Win Ratio 4.7
Outlier Loss Ratio 3.26
MTD 0.26
3M 0.23
6M 0.97
YTD 1.75
1Y 1.75
3Y (ann.) 1.76
5Y (ann.) 1.76
10Y (ann.) 1.76
All-time (ann.) 1.76
Best Day 0.12
Worst Day -0.07
Best Month 0.44
Worst Month -0.14
Best Year 1.75
Worst Year 1.75
Avg. Drawdown -0.04
Avg. Drawdown Days 8
Recovery Factor 7.51
Ulcer Index 1.45
Avg. Up Month 0.15
Persist Backtest to DB (optional )
In [ ]:
session.add( tsExecuteEngine )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst)
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")
In [ ]:
 

Portfolios

Portfolio A

  1. Portfolio A: Long and SMA Trade Strategies for US Indixes

    Description:

     1. Portfolio with 6 trading strategies
     2. $1.2M Budget
     3. No-Rebalance during the backtest 
     4. 100% capital invested
     5. Portfolio investment using equal weights for each trade strategy
    
    

    Trade Strategies:

     1. Three trade strategies: Nasdaq, S&P 500, and DOW Jones with buy-and-hold
     2. Three trade strategies: Nasdaq, S&P 500, and DOW Jones using SMA 
    
    

    Backtest:

     1. Type: regular
     2. Test Period: 
         1. Begin Date = 2001-01-01 
         2. End Date = 2001-12-31 
Portfolio Trade Assets
In [8]:
portfolio_trade_assets   = [ "^DJI", "^IXIC", "^GSPC" ]
Market Data Manager
In [9]:
dirPathMarketData = '/Users/gustavozambrana/Google Drive/Python/Projects/Trade_Engine/Data/US_Market_Indixes'

supportedTradeAssets   = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str           = "2000-01-01"
end_date_str           = None

ts_marketdat_mng = TradeStrategyMarketDataMng(\
        marketDataProviderName = "yahoofinance",
        supportedTradeAssets   = supportedTradeAssets,
        stock_price_col_name   = "Adj Close",
        fileNameMarketData     = "US_Indixes_And_ETFs_MrkData",
        dirPathMarketData      = dirPathMarketData,
        beg_date_str           = beg_date_str,
        end_date_str           = end_date_str,
        interval               = "1d"  ) 
2021-10-27 11:05:58,057 [INFO] root: Found previous Market data previously loaded to specified file and dir.
Pipeline Data Manager
Define Indicators & Signals

This is a second more detail approach to built a SMA trade strategy versus the example SMA Test Trade Strategy

  • Use this approach if you want total control of the rules, implement your own. The other approach just wraps this JSON and the other models built-in in a wrapper function to do most of the plumming.
  • Define the rules to create the SMA signals via JSON dict
  • Used a 20-day SMA and a 100-day SMA for signaled-generation
  • The Adj Close column from the market data will be used for the calculations
  • The following open source library is leveraged for the SMA calculations: https://technical-analysis-library-in-python.readthedocs.io/en/latest/ta.html#trend-indicators
  • The configuration of the library and method invocation is specified dynamically via the inputs:
    1. package
    2. class_name
    3. input_param_series
    4. input_param_series_mkd_col
    5. input_params_other Note:
      • input_param_series list of inputs are mapped to the input_param_series_mkd_col list of columns, which are extracted from the Market Data.
      • input_params_other are additional inputs the class takes in the constructor (see doc reference)
  • The output is generated by the method specified by output_generating_funcs, a Pandas Series is expected for the return from the method (the standard usage in the technical analysis library )
  • The output return Pandas Series is stored in a dataframe column in the pipeline object, it is specified via output_pipeline_cols
  • Multiple methods can be specified and multiple pipeline output columns, for SMA is not necessary, but for other indicators such as Bollinger Bands necessary
  • The rules for creating the SMA signals are defined via the "signals" part of the JSON. For SMA is just a matter of expressing the relation between the fast and slow moving averages
In [10]:
json_dat = {
    "version"    : "1.0",
    
    "indicators" : {
        
        "SMA" :  {
            "ta_indicators" : {
                  "sma_20": {
                      "package"                   : "ta.trend",
                      "class_name"                : "SMAIndicator",
                      "input_param_series"        : ["close"],
                      "input_param_series_mkd_col": ["Adj Close"],
                      "input_params_other"        : { "window": 20, "fillna": False },
                      "output_pipeline_cols"      : [ "sma_20" ],
                      "output_generating_funcs"   : [ "sma_indicator()" ]
                   },

                   "sma_100": {
                      "package"                   : "ta.trend",
                      "class_name"                : "SMAIndicator",
                      "input_param_series"        : ["close"],
                      "input_param_series_mkd_col": ["Adj Close"],
                      "input_params_other"        : { "window": 100, "fillna": False },
                      "output_pipeline_cols"      : [ "sma_100" ],
                      "output_generating_funcs"   : [ "sma_indicator()" ]
                   }   
            },     

            "signals" : {
                  "sma20_gt_sma100": {
                      "columns"       : [ "sma_20", "sma_100" ],
                      "relationship"  : "gt",
                      "signal_col"    : "sma20_gt_sma100"
                   },
                
                   "sma20_lt_sma100": {
                      "signal_gen_func" : "signalSampleCreator",
                      "func_args"       : { },
                      "signal_col"      : "sma20_lt_sma100"
                   },         
            }             
        },
    },
}

def signalSampleCreator(df : pd.DataFrame, **kwargs ) -> pd.core.series.Series :
    return df["sma_20"] < df["sma_100"]
Define Pipeline Manager
In [11]:
taPipilineObj = TALibPipelineBuilder( trade_assets = portfolio_trade_assets, 
                                      json_dat = json_dat, 
                                      signalgen_func_dict = { 'signalSampleCreator' : signalSampleCreator } )
In [12]:
ts_model_pipline_mng = TradeStrategyModelPipelineDataMng(\
                        tsMarketDataMng         = ts_marketdat_mng,
                        modelPipelineBuilder    = taPipilineObj,
                        fileNameMarketData      = "US_Indixes_And_ETFs_PipelineData",
                        forceCreatePipelineData = True,
                        dirPathMarketData       = dirPathMarketData ) 
In [13]:
dfx = ts_model_pipline_mng.getAllModelDataPipelineDataForStockSymbol(stockSymbol = "^GSPC" )
dfx
Out[13]:
Index Adj Close Close High Low Open Volume sma_20 sma_100 sma20_gt_sma100 sma20_lt_sma100
Date
2000-05-24 ^GSPC 1399.050049 1399.050049 1401.750000 1361.089966 1373.859985 1152300000 1426.065509 1428.297998 0 1
2000-05-25 ^GSPC 1381.520020 1381.520020 1411.650024 1373.930054 1399.050049 984500000 1421.895508 1427.560999 0 1
2000-05-26 ^GSPC 1378.020020 1378.020020 1391.420044 1369.750000 1381.520020 722600000 1418.175006 1427.346998 0 1
2000-05-30 ^GSPC 1422.449951 1422.449951 1422.449951 1378.020020 1378.020020 844200000 1415.885004 1427.550398 0 1
2000-05-31 ^GSPC 1420.599976 1420.599976 1434.489990 1415.500000 1422.439941 960500000 1414.600500 1427.721898 0 1
... ... ... ... ... ... ... ... ... ... ... ...
2021-09-14 ^GSPC 4443.049805 4443.049805 4485.680176 4435.459961 4479.330078 2568730000 4484.140967 4318.467500 1 0
2021-09-15 ^GSPC 4480.700195 4480.700195 4486.870117 4438.370117 4447.490234 3154760000 4485.771973 4321.472803 1 0
2021-09-16 ^GSPC 4473.750000 4473.750000 4485.870117 4443.799805 4477.089844 3321030000 4489.445972 4324.334102 1 0
2021-09-17 ^GSPC 4432.990234 4432.990234 4471.520020 4427.759766 4469.740234 5622210000 4490.805493 4326.796802 1 0
2021-09-20 ^GSPC 4357.729980 4357.729980 4402.950195 4305.910156 4402.950195 2598257000 4486.608496 4328.542300 1 0

5365 rows × 11 columns

Simulation Broker
In [14]:
brokerTradingObj = SimBrokerTrading()
Trade Strategies, Trade Investment Manager, and Trade Asset Register Items
In [15]:
# Conducting a backtest for a Trade Strategy requires:
#
#    1. A Trade Strategy Model 
#         - A TS Model is associated with only on trade asset 
#         - References a Market Data Manager 
#         - Trading Rules: Entry, Exit,Stop-Loss, Trail-Stop-Loss, etc.  (only Entry rules are required)
#         - Each Trading Action may have a Pipeline Data Manager associated with. 
#           - For example: For using SMA to enter/exit trades, the signasl must be computed based on the
#                        Market Data and SMA indicators/signals configured
#           - Different trade actions might share the same pipeline manager or create different onces
#         - Each Trading Action has their own configuration/metadata
#           - Entry Rules: 
#               Decide how to combine signals and which signals to enter/exit
#               Entry Policies:  
#                  - Only enter a trade if the last n dates/periods were marked for entering a trade
#                  - Only enter a trade if there is a cross-over signal (from buy to sell, or sell to buy)
#               More complex configuration options are availabe for creating entry rules based on an ensemble
#               of entry rule algorithms. This will be explained and detail in other examples.
#           
#    2. A Broker to conduct the trades with 
#         - can be shared across Trade Strategies, but no required
#
#    3. A Trade Strategy Investment Manager
#         - Manages the budget and spending rules (max/min to invest)
#         - Trades 
#         - Interfaces with Broker objects to place, cancel, alter trades
#         - Other investment metadata rules
#         - Works with Portfolio Investment Managers to rebalance funds across a portfolio
#
#    4. A Trade Asset Register Item
#         - This is a compose object to have all necessary information to conduct a backtest 
#           either as a single item, or as part of a portfolio
#         - The dates and characteristics of the backtest execution are defined separately


# Each Trade Register Item Object has:
#   - A Name 
#   - One Trade Strategy
#       + Each Trade Strategy has one or more actions defined (only entry rules are mandatory)
#           a) Entry Rules
#           b) Exit Rules
#           c) Stop Loss and/or Trail Stop Rules
#           d) Position Sizing Rules per trade 
#           etc.
#   - One Investment Manager
#   - A broker to trade with (simulation, or paper trading)

taRegisterItems = [ ]

for trade_asset in portfolio_trade_assets :
    
    # *** Trading Rules Model, generating buy, sell, hold trade decisions based on long/short signals
    # *** N number of signals can be configured to entered long or short trades, the 
    # *** long_signals_bool_logic or short_signals_bool_logic control determine logic to apply
    # *** See also: VotingTradingRulesModel() to derive rules based on voting metadata
    
    classic_model_enter = TradingRulesModel( name = "SMA_Enter",
                                       enter_long_signals  = [ "sma20_gt_sma100" ],
                                       enter_short_signals = [ "sma20_lt_sma100" ],
                                       long_signals_bool_logic  =  "and",  
                                       short_signals_bool_logic  =  "and"   ) 
    
    classic_model_exit = TradingRulesModel( name = "SMA_Exit",
                                       enter_long_signals  = [ "sma20_gt_sma100" ],
                                       enter_short_signals = [ "sma20_lt_sma100" ],
                                       long_signals_bool_logic  =  "and",  
                                       short_signals_bool_logic  =  "and"   ) 
    
    # *** TS Entry Rules 
    # *** Uses Trading Rules Model configured above to determine when to enter a trade
    
    ts_entry = TradeEnterClassicStrategy( 
                         classic_trading_model  = CacheTradingModel( name = "SMA_20_AND_100_Enter",
                                                                     classic_model = classic_model_enter ),
                         ts_model_pipline_mng   = ts_model_pipline_mng )  
 
    # *** TS Exit Rules 
    # *** Uses Trading Rules Model configured above to determine when to exit a trade,
    # *** The exit rules can used a different set of signals (EMA, BB, or AI based rules) than entry rules,
    # *** in this example the entry and exit rules are based on the same set of SMA trading rules
    
    ts_exit = TradeExitClassicStrategy( 
                         classic_trading_model  = CacheTradingModel( name = "SMA_20_AND_100_Exit",
                                                                     classic_model = classic_model_exit ),
                         ts_model_pipline_mng   = ts_model_pipline_mng )  
    
    # *** Trade Strategy 
    
    ts_model = TradeStrategyBaseModelPersist(\
                    trade_asset               = trade_asset,
                    ts_marketdat_mng          = ts_marketdat_mng,
                    ts_enter                  = TradeEnterStack( tsEntries = [ ts_entry ] ),
                    ts_exit                   = TradeExitStack( tsExits = [ ts_exit ] ),                    
                    model_type                = "sma",
                    model_version             = "1.0",
                    market_data_period        = MarketDataPeriod.Day,
                ) 
    
    # *** Trade Strategy Investment Manager 
    
    taInvMng = TradingAssetInvMngBase(\
                                    trade_asset                = trade_asset,
                                    minPeriodsBetweenTrades    = 1,
                                    initInvestment             = 1000000.0, 
                                    capPercentToInvestPerTrade = 100.0,
                                    minInvestPercent           = 5.0,
                                    min_account_balance        = 1000.0 )

    # *** Trade Register Item
    # *** This object has all configuration defined to execute a given trade strategy,
    # *** It can be executed individually in backtest or as part of a portfolio
    
    ta_registered_item = TradingAssetRegisterItem(\
                trade_name                    = "TA - SMA for: {0}".format(trade_asset), 
                ts_model                      = ts_model,
                tradingExecutionType          = TradingAssetExecutionType.Simulation,
                tradingBrokerObj              = brokerTradingObj,
                tradingAssetInvMngObj         = taInvMng )  
 
    taRegisterItems.append(ta_registered_item)
    
Portfolio Investment Manager
In [16]:
# *** Porttfolio Investment Manager across all individual trade strategies investment managers
# *** Role: 
# ***    1) Managed investment funds across n number of trade strategies
# ***    2) Rebalance portfolio periodically or never
# ***    3) Portfolio Policy Weights 
# ***          equal weights (default)
# ***          MinimumVariance
# ***          User defined 
# ***    4) Track Portfolio level returns and metrics
# ***          Individual Trade Strategies return and metrics tracked through their 
# ***          investment managers
# ***          Portfolio funds are split across each trade strategy investment manager based on the
# ***          portfolio weights

portfInvMng = PortfolioInvMng(\
                  name                       = "Portfolio Inv. Manager for US-Indexes - SMA Algo",
                  initInvestment             = 12000000.0, 
                  portfRebalanceFreq         = PortfolioRebalanceFrequency.Never,
                  portfRebalancePeriods      = 1,
                  minInvestPercent           = 5.0,
                  min_account_balance        = 1000.0,     
                  minPeriodsBetweenTrades    = 1,
                  capPercentToInvestPerTrade = 100.0 )
Trade Register Items Portfolio
In [17]:
# *** Set of Trade Register Items
#
# Configuration Summary:
#    - Each set has 1 to n trade register items as previously described 
#    - Optionally add long only trade strategies for all unique trade assets in the
#      portfolio 
#           - (Dow, Nasdaq, and S&P 500 for this portfolio) in this example
#           - Might be useful for bench marking trade strategies
#    - Each set has one Investment Portfolio Manager
#       - portfolio funds allocated per portfolio policy rules and re-balanced (if defined), 
#         across all trade strategies


portf_registered_obj = PortfolioRegisterItem(\
                            name                 = "Portfolio A, US-Indexes using SMA and Long strategies",
                            taRegisterItems      = taRegisterItems,
                            portfolioInvMngObj   = portfInvMng,
                            tradingExecutionType = TradingAssetExecutionType.Simulation,
                            add_long_only_ts     = True )
2021-10-27 11:06:13,163 [INFO] root: *** Adding long only trade strategies for : {'^GSPC', '^IXIC', '^DJI'}
Persist to DB (optional)
In [18]:
session.add( portf_registered_obj )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")
 done
Re-Store from DB (optional)
In [19]:
session.expunge_all()
del portf_registered_obj

for tsObj in session.query(PortfolioRegisterItem):  
    print(tsObj.name)
    if  tsObj.name  == "Portfolio A, US-Indexes using SMA and Long strategies" :
        break

portf_registered_obj = tsObj
print(portf_registered_obj.id, portf_registered_obj.name)
2021-10-27 11:06:20,847 [INFO] root: PortfolioRegisterItem init called. 
Portfolio of US-Indexes using SMA and Long strategies
1 Portfolio of US-Indexes using SMA and Long strategies
Execute Backtest
In [20]:
tsExecuteEngine = BacktestExecution( \
                    name = "Backtest for SMA based Trade Strategies",
                    timePeriod = DatasetDef(datasetType = DatasetType.Testing,
                                            strBegDate = "2001-01-01", 
                                            strEndDate = "2001-12-31" ),
                    trade_asset_registered_item = portf_registered_obj )
In [ ]:
tsExecuteEngine.evaluate()
Backtest Metrics
Execution & Investment Metrics
In [22]:
tsExecuteEngine.getExecutionMetrics()
Out[22]:
TA_Reg_Name TA_Reg_Id Inv_Mng_Id Inv_Mng_Parent_Id Is_Portfolio Num_Trades_Executing Num_Trades_Completed Init_Capital Final_Capital Final_Inv_Capital Cum_Return Backtest_Status
0 Portfolio of US-Indexes using SMA and Long str... 1 1 NaN Yes 0 21 12000000.0 1.082878e+07 0.0 -0.097602 Completed
1 TA - SMA for: ^DJI 1 1 1.0 No 0 6 2000000.0 1.871721e+06 0.0 -0.064139 Completed
2 TA - SMA for: ^IXIC 2 2 1.0 No 0 8 2000000.0 1.720096e+06 0.0 -0.139952 Completed
3 TA - SMA for: ^GSPC 3 3 1.0 No 0 4 2000000.0 1.862138e+06 0.0 -0.068931 Completed
4 Long-Only Trade Strategy for ^GSPC 4 4 1.0 No 0 1 2000000.0 1.789374e+06 0.0 -0.105313 Completed
5 Long-Only Trade Strategy for ^IXIC 5 5 1.0 No 0 1 2000000.0 1.702247e+06 0.0 -0.148877 Completed
6 Long-Only Trade Strategy for ^DJI 6 6 1.0 No 0 1 2000000.0 1.883204e+06 0.0 -0.058398 Completed
Performance Metrics
In [23]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ]
Out[23]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
0 Portfolio of US-Indexes using SMA and Long str... Yes 2001-01-03 2001-12-31 0.79 -0.1 -0.1 -1.26 -0.13 0.03 -0.03
1 TA - SMA for: ^DJI No sma ^DJI 2001-01-03 2001-12-31 1.0 -0.06 -0.06 -0.25 -0.2 0.06 -0.04
2 TA - SMA for: ^IXIC No sma ^IXIC 2001-01-03 2001-12-31 1.0 -0.14 -0.14 -0.19 -0.38 0.08 -0.14
3 TA - SMA for: ^GSPC No sma ^GSPC 2001-01-03 2001-12-31 1.0 -0.07 -0.07 -0.28 -0.24 0.04 -0.05
4 Long-Only Trade Strategy for ^GSPC No long ^GSPC 2001-01-03 2001-12-31 1.0 -0.11 -0.11 -0.42 -0.3 0.05 -0.05
5 Long-Only Trade Strategy for ^IXIC No long ^IXIC 2001-01-03 2001-12-31 1.0 -0.15 -0.15 -0.17 -0.5 0.14 -0.07
6 Long-Only Trade Strategy for ^DJI No long ^DJI 2001-01-03 2001-12-31 1.0 -0.06 -0.06 -0.18 -0.27 0.04 -0.07
In [24]:
tsExecuteEngine.getSummaryMetrics().T.head(60)
Out[24]:
0 1 2 3 4 5 6
ta_reg_item_name Portfolio of US-Indexes using SMA and Long str... TA - SMA for: ^DJI TA - SMA for: ^IXIC TA - SMA for: ^GSPC Long-Only Trade Strategy for ^GSPC Long-Only Trade Strategy for ^IXIC Long-Only Trade Strategy for ^DJI
ta_reg_item_id 1 1 2 3 4 5 6
is_portfolio Yes No No No No No No
model_type sma sma sma long long long
trade_asset ^DJI ^IXIC ^GSPC ^GSPC ^IXIC ^DJI
test_period_len_days 364 364 364 364 364 364 364
tr_period_len_days 0 0 0 0 0 0 0
val_period_len_days 0 0 0 0 0 0 0
index Strategy Strategy Strategy Strategy Strategy Strategy Strategy
Start Period 2001-01-03 2001-01-03 2001-01-03 2001-01-03 2001-01-03 2001-01-03 2001-01-03
End Period 2001-12-31 2001-12-31 2001-12-31 2001-12-31 2001-12-31 2001-12-31 2001-12-31
Risk-Free Rate 0.0 0.0 0.0 0.0 0.0 0.0 0.0
Time in Market 0.79 1.0 1.0 1.0 1.0 1.0 1.0
Cumulative Return -0.1 -0.06 -0.14 -0.07 -0.11 -0.15 -0.06
CAGR% -0.1 -0.06 -0.14 -0.07 -0.11 -0.15 -0.06
Sharpe -1.26 -0.25 -0.19 -0.28 -0.42 -0.17 -0.18
Sortino -1.58 -0.36 -0.26 -0.39 -0.59 -0.25 -0.25
Sortino/√2 -1.12 -0.26 -0.19 -0.28 -0.42 -0.18 -0.18
Max Drawdown -0.13 -0.2 -0.38 -0.24 -0.3 -0.5 -0.27
Longest DD Days 332 182 270 270 334 340 223
Volatility (ann.) 0.08 0.19 0.4 0.19 0.21 0.43 0.21
Calmar -0.78 -0.32 -0.37 -0.29 -0.36 -0.3 -0.22
Skew -0.64 0.32 -0.42 0.0 0.1 0.65 -0.47
Kurtosis 10.6 2.71 3.89 1.32 1.59 2.92 3.72
Expected Daily % -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0
Expected Monthly % -0.01 -0.01 -0.01 -0.01 -0.01 -0.01 -0.01
Expected Yearly % -0.1 -0.06 -0.14 -0.07 -0.11 -0.15 -0.06
Kelly Criterion -0.19 -0.02 -0.02 -0.02 -0.04 -0.01 -0.02
Risk of Ruin 0.0 0.0 0.0 0.0 0.0 0.0 0.0
Daily Value-at-Risk -0.01 -0.02 -0.04 -0.02 -0.02 -0.04 -0.02
Expected Shortfall (cVaR) -0.01 -0.02 -0.04 -0.02 -0.02 -0.04 -0.02
Gain/Pain Ratio -0.28 -0.04 -0.03 -0.04 -0.07 -0.03 -0.03
Gain/Pain (1M) -0.79 -0.18 -0.1 -0.15 -0.26 -0.1 -0.13
Payoff Ratio 0.74 0.96 1.08 0.98 1.0 0.95 0.97
Profit Factor 0.72 0.96 0.97 0.96 0.93 0.97 0.97
Common Sense Ratio 0.54 1.11 1.11 1.12 0.93 0.94 0.96
CPC Index 0.26 0.46 0.49 0.46 0.45 0.47 0.47
Tail Ratio 0.76 1.16 1.15 1.17 1.0 0.97 0.99
Outlier Win Ratio 6.68 3.49 3.19 3.02 3.82 3.6 3.67
Outlier Loss Ratio 5.09 3.52 2.99 3.18 3.23 2.94 3.6
MTD 0.01 0.03 0.01 0.01 0.01 0.01 0.02
3M 0.02 -0.05 -0.18 -0.07 0.1 0.3 0.13
6M -0.03 0.09 -0.07 0.02 -0.06 -0.1 -0.05
YTD -0.1 -0.06 -0.14 -0.07 -0.11 -0.15 -0.06
1Y -0.1 -0.06 -0.14 -0.07 -0.11 -0.15 -0.06
3Y (ann.) -0.1 -0.06 -0.14 -0.07 -0.11 -0.15 -0.06
5Y (ann.) -0.1 -0.06 -0.14 -0.07 -0.11 -0.15 -0.06
10Y (ann.) -0.1 -0.06 -0.14 -0.07 -0.11 -0.15 -0.06
All-time (ann.) -0.1 -0.06 -0.14 -0.07 -0.11 -0.15 -0.06
Best Day 0.03 0.06 0.08 0.04 0.05 0.14 0.04
Worst Day -0.03 -0.04 -0.14 -0.05 -0.05 -0.07 -0.07
Best Month 0.01 0.1 0.34 0.1 0.08 0.21 0.09
Worst Month -0.04 -0.08 -0.21 -0.09 -0.09 -0.22 -0.11
Best Year -0.1 -0.06 -0.14 -0.07 -0.11 -0.15 -0.06
Worst Year -0.1 -0.06 -0.14 -0.07 -0.11 -0.15 -0.06
Avg. Drawdown -0.06 -0.09 -0.09 -0.05 -0.09 -0.15 -0.15
Avg. Drawdown Days 168 69 37 37 89 88 118
Recovery Factor -0.77 -0.32 -0.37 -0.28 -0.35 -0.3 -0.21
Ulcer Index 1.11 1.07 1.04 1.04 1.04 1.02 1.08
Avg. Up Month 0.01 0.04 0.12 0.06 0.04 0.11 0.04
Persist Backtest to DB (optional )
In [25]:
session.add( tsExecuteEngine )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst)
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")
 done
Re-Store Backtest
In [26]:
session.expunge_all()
del tsExecuteEngine

for tsObj in session.query(BacktestExecution):  
    print(tsObj.name)
    if  tsObj.name  == "Backtest for SMA based Trade Strategies" :
        break

tsExecuteEngine = tsObj
print(tsExecuteEngine.id, tsExecuteEngine.name)
2021-10-27 11:07:52,246 [INFO] root: BacktestExecution init called. 
2021-10-27 11:07:52,255 [INFO] root: PortfolioRegisterItem init called. 
2021-10-27 11:07:52,256 [INFO] root: Loaded TradingAssetRegisterBase object
2021-10-27 11:07:52,266 [INFO] root: BacktestExecutionDatasets init called. 
Backtest for SMA based Trade Strategies
1 Backtest for SMA based Trade Strategies
In [27]:
tsExecuteEngine.getExecutionMetrics()
2021-10-27 11:07:52,374 [INFO] root: PortfolioInvMng init called. 
2021-10-27 11:07:52,375 [INFO] root: PortfolioInvMng init called. 
2021-10-27 11:07:52,392 [INFO] root: TradingAssetRegisterItem init called. 
2021-10-27 11:07:52,393 [INFO] root: TradingAssetRegisterItem init called. 
2021-10-27 11:07:52,393 [INFO] root: TradingAssetRegisterItem init called. 
2021-10-27 11:07:52,394 [INFO] root: TradingAssetRegisterItem init called. 
2021-10-27 11:07:52,395 [INFO] root: TradingAssetRegisterItem init called. 
2021-10-27 11:07:52,396 [INFO] root: TradingAssetRegisterItem init called. 
**** TradingAssetInvMngBase init called. 
2021-10-27 11:07:52,403 [INFO] root: TradingAssetInvMngBase init called. 
**** TradingAssetInvMngBase init called. 
2021-10-27 11:07:52,422 [INFO] root: TradingAssetInvMngBase init called. 
**** TradingAssetInvMngBase init called. 
2021-10-27 11:07:52,441 [INFO] root: TradingAssetInvMngBase init called. 
**** TradingAssetInvMngBase init called. 
2021-10-27 11:07:52,458 [INFO] root: TradingAssetInvMngBase init called. 
**** TradingAssetInvMngBase init called. 
2021-10-27 11:07:52,476 [INFO] root: TradingAssetInvMngBase init called. 
**** TradingAssetInvMngBase init called. 
2021-10-27 11:07:52,492 [INFO] root: TradingAssetInvMngBase init called. 
/Users/gustavozambrana/venvs/CFRM505/lib/python3.7/site-packages/sqlalchemy/orm/loading.py:628: SAWarning: Loading context for <PortfolioInvMng at 0x7f9be8832a50> has changed within a load/refresh handler, suggesting a row refresh operation took place. If this event handler is expected to be emitting row refresh operations within an existing load or refresh operation, set restore_load_context=True when establishing the listener to ensure the context remains unchanged when the event handler completes.
  "handler completes." % (state_str(state),)
Out[27]:
TA_Reg_Name TA_Reg_Id Inv_Mng_Id Inv_Mng_Parent_Id Is_Portfolio Num_Trades_Executing Num_Trades_Completed Init_Capital Final_Capital Final_Inv_Capital Cum_Return Backtest_Status
0 Portfolio of US-Indexes using SMA and Long str... 1 1 NaN Yes 0 21 12000000.0 1.082878e+07 0.0 -0.097602 Completed
1 TA - SMA for: ^DJI 1 1 1.0 No 0 6 2000000.0 1.871721e+06 0.0 -0.064139 Completed
2 TA - SMA for: ^IXIC 2 2 1.0 No 0 8 2000000.0 1.720096e+06 0.0 -0.139952 Completed
3 TA - SMA for: ^GSPC 3 3 1.0 No 0 4 2000000.0 1.862138e+06 0.0 -0.068931 Completed
4 Long-Only Trade Strategy for ^GSPC 4 4 1.0 No 0 1 2000000.0 1.789374e+06 0.0 -0.105313 Completed
5 Long-Only Trade Strategy for ^IXIC 5 5 1.0 No 0 1 2000000.0 1.702247e+06 0.0 -0.148877 Completed
6 Long-Only Trade Strategy for ^DJI 6 6 1.0 No 0 1 2000000.0 1.883204e+06 0.0 -0.058398 Completed

Portfolio B

Portfolio B: Long and AI LSTM based Strategies for US Indixes

Description:

1. Portfolio with 6 trading strategies
2. $1.2M Budget
3. No-Rebalance during the backtest 
4. 100% capital invested
5. Portfolio investment using equal weights for each trade strategy

Trade Strategies:

1. Three trade strategies: Nasdaq, S&P 500, and DOW Jones with buy-and-hold
2. Three trade strategies: Nasdaq, S&P 500, and DOW Jones using LSTM AI Model 

Backtest:

1. Type: regular
2. AI Models Fit Date Ranges
    1. Training Period: 
        1. Begin Date = 2001-01-01 
        2. End Date   = 2005-12-31  
    2. Validation Period: 
        1. Begin Date = 2006-01-01 
        2. End Date   = 2007-06-30   
4. Test Period: 
    1. Begin Date = 2008-01-01 
    2. End Date   = 2008-12-31 
Portfolio Trade Assets
In [30]:
portfolio_trade_assets   = [ "^DJI", "^IXIC", "^GSPC" ]
Market Data Manager
In [31]:
dirPathMarketData = '/Users/gustavozambrana/Google Drive/Python/Projects/Trade_Engine/Data/US_Market_Indixes'

supportedTradeAssets   = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str           = "2000-01-01"
end_date_str           = None

ts_marketdat_mng = TradeStrategyMarketDataMng(\
        marketDataProviderName = "yahoofinance",
        supportedTradeAssets   = supportedTradeAssets,
        stock_price_col_name   = "Adj Close",
        fileNameMarketData     = "US_Indixes_And_ETFs_MrkData",
        dirPathMarketData      = dirPathMarketData,
        beg_date_str           = beg_date_str,
        end_date_str           = end_date_str,
        interval               = "1d"  ) 
2021-10-28 14:00:27,003 [INFO] root: Found previous Market data previously loaded to specified file and dir.
Pipeline Data Manager
In [32]:
ts_model_pipline_mng_b = TradeStrategyModelPipelineDataMng(\
                            tsMarketDataMng    = ts_marketdat_mng,
                            package            = "trade_engine.model.ai.WaveNet_RNN_AI_PipelineBuilder",
                            model_class_name   = "WaveNet_RNN_AI_PipelineBuilder",
                            fileNameMarketData = "WaveNet_RNN_AI_Pipeline_Data_Portf_B",
                            forceCreatePipelineData = True,
                            dirPathMarketData  = dirPathMarketData )
Found module already imported: WaveNet_RNN_AI_PipelineBuilder
In [33]:
ts_model_pipline_mng_b.getAllModelDataPipelineDataForStockSymbol(stockSymbol = "^GSPC" )
Out[33]:
Adj Close Close High Low Open Volume Index
Date
2000-01-03 0.201711 0.201711 0.203276 0.199999 0.204862 0.051867 ^GSPC
2000-01-04 0.187257 0.187257 0.197360 0.189389 0.201224 0.058822 ^GSPC
2000-01-05 0.187954 0.187954 0.186465 0.184270 0.186753 0.065713 ^GSPC
2000-01-06 0.188301 0.188301 0.186110 0.188008 0.187451 0.066326 ^GSPC
2000-01-07 0.198149 0.198149 0.193789 0.190245 0.187799 0.078299 ^GSPC
... ... ... ... ... ... ... ...
2021-09-14 0.975676 0.975676 0.984374 0.976878 0.985465 0.199336 ^GSPC
2021-09-15 0.985429 0.985429 0.984683 0.977633 0.977208 0.252131 ^GSPC
2021-09-16 0.983629 0.983629 0.984423 0.979040 0.984884 0.267110 ^GSPC
2021-09-17 0.973070 0.973070 0.980696 0.974882 0.982978 0.474420 ^GSPC
2021-09-20 0.953575 0.953575 0.962889 0.943298 0.965657 0.201996 ^GSPC

5464 rows × 7 columns

Simulation Broker
In [34]:
brokerTradingObj = SimBrokerTrading()
Trade Strategies, Trade Investment Manager, and Trade Asset Register Items
In [45]:
# Conducting a backtest for a Trade Strategy requires:
#
#    1. A Trade Strategy Model 
#         - A TS Model is associated with only on trade asset 
#         - References a Market Data Manager 
#         - Trading Rules: Entry, Exit,Stop-Loss, Trail-Stop-Loss, etc.  (only Entry rules are required)
#         - Each Trading Action may have a Pipeline Data Manager associated with. 
#           - For example: For using SMA to enter/exit trades, the signasl must be computed based on the
#                        Market Data and SMA indicators/signals configured
#           - Different trade actions might share the same pipeline manager or create different onces
#         - Each Trading Action has their own configuration/metadata
#           - Entry Rules: 
#               Decide how to combine signals and which signals to enter/exit
#               Entry Policies:  
#                  - Only enter a trade if the last n dates/periods were marked for entering a trade
#                  - Only enter a trade if there is a cross-over signal (from buy to sell, or sell to buy)
#               More complex configuration options are availabe for creating entry rules based on an ensemble
#               of entry rule algorithms. This will be explained and detail in other examples.
#           
#    2. A Broker to conduct the trades with 
#         - can be shared across Trade Strategies, but no required
#
#    3. A Trade Strategy Investment Manager
#         - Manages the budget and spending rules (max/min to invest)
#         - Trades 
#         - Interfaces with Broker objects to place, cancel, alter trades
#         - Other investment metadata rules
#         - Works with Portfolio Investment Managers to rebalance funds across a portfolio
#
#    4. A Trade Asset Register Item
#         - This is a compose object to have all necessary information to conduct a backtest 
#           either as a single item, or as part of a portfolio
#         - The dates and characteristics of the backtest execution are defined separately


# Each Trade Register Item Object has:
#   - A Name 
#   - One Trade Strategy
#       + Each Trade Strategy has one or more actions defined (only entry rules are mandatory)
#           a) Entry Rules
#           b) Exit Rules
#           c) Stop Loss and/or Trail Stop Rules
#           d) Position Sizing Rules per trade 
#           etc.
#   - One Investment Manager
#   - A broker to trade with (simulation, or paper trading)

taRegisterItems = [ ]

for trade_asset in portfolio_trade_assets :
    
    # LSTM Trading Model, Configure with Trading Rules 
    #
    # There are two parts two configured an AI Trading Model:
    #
    #    1) Defined the Actual AI Architecture and configured it:
    #         - for this example it is an LSTM model with two layers, the model params are customed
    #         - This LSTM network uses two x-features for predictions, and predicts 5 steps ahead
    #         - AI Models are derived from the class : AI_ModelBase 
    #
    #.   2) Defined the Trading Rules for an AI Model
    #         - How predictions from an AI model translated to invest/no-invest signals, and 
    #           trade type (long or short)
    #         - AI Models are derived from the class : AI_TradingModelBase 
    #         - The WaveNet_RNN_AI_TradingModel class has a generic set of trading rules for DL
    #           time series forecasting models
    #         - The Trading Model feeds the Pipeline data built for the AI model in tensor format
    #
    #         - Configured the trading model metadata
    #                - x-features : 'Adj Close', 'Volume'  { for predicting , could be more or less}
    #                - y-label    : 'Adj Close'            { just predict adj close }
    #                - creates time series that are 50 steps long for predicting
    #                - The AI time series model will predict 5 steps ahead 
    #            
    #         - The following trading metadata rules are defined with the following params:           
    #              a) trad_pred_rule = 
    #                     i)  WaveNet_RNN_AI_Trading_Rules.n_pred_ahead  
    #                            { use n days ahead prediction } or
    #                     ii) WaveNet_RNN_AI_Trading_Rules.n_pred_mean  
    #                            { predict using the mean of n days ahead }        
    #               b) trad_pred_dat  = [ n ]   { predict using n periods ahead, 0 = Next Period }
    #               c) extend_trade_exit_dyn    = [ True, False ]
    #                     Yes, an open trade will be extended based on current forecast of data
    #                     ex: If a trade was opened in a long position with 5 days ahead prediction, 
    #                         if option is enable, every period, the trade will be analyzed for extending  
    #               d) re_evaluate_forecast_exit_dyn  = [ True, False ]  
    #                      True = exit trade earlier than first forecast, base on new data
    #                      ex: if a trade was opened in a long position using 5 days ahead forecast,
    #                          if this option is enable, the trade can be exited after any period,
    #                          if the LSTM Model starts predicting a different signal/trade-type than the
    #                          one entered.
    #

    num_x_features = 2 
    num_y_predict_ahead_periods = 5
    
    ai_model = LSTM_Model( epochs = 20, 
                           num_x_features         = num_x_features,
                           num_y_predictions      = num_y_predict_ahead_periods,
                           lstm_layers_neuros     = [ 20, 20 ],  # number of LSTM stack layers, and thier num of neurons
                           optimizer              = "adam",
                           activation             = "relu",
                           rand_seed              = 42 ) 
     
    ai_trading_model   = WaveNet_RNN_AI_TradingModel(\
                               name                           = "LSTM_{0}".format(trade_asset),
                               ai_model                       = ai_model,
                               num_x_features                 = num_x_features,
                               features                       = ['Adj Close', 'Volume'], 
                               features_label                 = 'Adj Close',
                               n_steps                        = 50, 
                               n_pred_ahead                   = num_y_predict_ahead_periods,
                               trad_pred_rule                 = WaveNet_RNN_AI_Trading_Rules.n_pred_ahead,
                               trad_pred_dat                  = [ 0 ], 
                               extend_trade_exit_dyn          = True,
                               re_evaluate_forecast_exit_dyn  = True )
    # *** TS Entry Rules 
    # *** Uses AI Trading Model configured above to determine when to enter a trade
    
    ts_enter_ai = TradeEnterAIStrategy(name = "Enter_LSTM",
                                       ai_trading_model = ai_trading_model, 
                                       ts_model_pipline_mng = ts_model_pipline_mng_b ) 
                                                     
    ts_enter_ai_set = TradeEnterStack( tsEntries = [ ts_enter_ai ],
                                       tsPolicy  = TradeEnterSetPolicy( \
                                                        lastn_match = 1,
                                                        votingPolicy = TradeEnterSetVotingPolicy.Majority ) 
                                     ) 

    # *** TS Exit Rules 
    # *** Uses AI Trading Model configured above to determine when to enter a trade
     
    ts_exit_ai = TradeExitAIStrategy(name = "Exit_LSTM",
                                     ai_trading_model = ai_trading_model,
                                     ts_model_pipline_mng = ts_model_pipline_mng_b ) 
                                                     
    ts_exit_ai_set = TradeExitStack( tsExits = [ ts_exit_ai] )
                                                      
    # *** Trade Strategy 
        
    ts_model = TradeStrategyBaseModelPersist(\
                    trade_asset               = trade_asset,
                    ts_marketdat_mng          = ts_marketdat_mng,
                    ts_enter                  = ts_enter_ai_set,
                    ts_exit                   = ts_exit_ai_set,                       
                    model_type                = "lstm",
                    model_version             = "1.0",
                    market_data_period        = MarketDataPeriod.Day,
                ) 
    
    # *** Trade Strategy Investment Manager 
    
    taInvMng = TradingAssetInvMngBase(\
                                    trade_asset                = trade_asset,
                                    minPeriodsBetweenTrades    = 1,
                                    initInvestment             = 1000000.0, 
                                    capPercentToInvestPerTrade = 100.0,
                                    minInvestPercent           = 5.0,
                                    min_account_balance        = 1000.0 )

    # *** Trade Register Item
    # *** This object has all configuration defined to execute a given trade strategy,
    # *** It can be executed individually in backtest or as part of a portfolio
    
    ta_registered_item = TradingAssetRegisterItem(\
                trade_name                    = "TA - LSTM for: {0}".format(trade_asset), 
                ts_model                      = ts_model,
                tradingExecutionType          = TradingAssetExecutionType.Simulation,
                tradingBrokerObj              = brokerTradingObj,
                tradingAssetInvMngObj         = taInvMng )  
 
    taRegisterItems.append(ta_registered_item)
    
Portfolio Investment Manager
In [46]:
# *** Porttfolio Investment Manager across all individual trade strategies investment managers
# *** Role: 
# ***    1) Managed investment funds across n number of trade strategies
# ***    2) Rebalance portfolio periodically or never
# ***    3) Portfolio Policy Weights 
# ***          equal weights (default)
# ***          MinimumVariance
# ***          User defined 
# ***    4) Track Portfolio level returns and metrics
# ***          Individual Trade Strategies return and metrics tracked through their 
# ***          investment managers
# ***          Portfolio funds are split across each trade strategy investment manager based on the
# ***          portfolio weights

portfInvMng = PortfolioInvMng(\
                  name                       = "Portfolio Inv. Manager for US-Indexes - LSTM Algo",
                  initInvestment             = 12000000.0, 
                  portfRebalanceFreq         = PortfolioRebalanceFrequency.Never,
                  portfRebalancePeriods      = 1,
                  minInvestPercent           = 5.0,
                  min_account_balance        = 1000.0,     
                  minPeriodsBetweenTrades    = 1,
                  capPercentToInvestPerTrade = 100.0 )
Trade Register Items Portfolio
In [47]:
# *** Set of Trade Register Items
#
# Configuration Summary:
#    - Each set has 1 to n trade register items as previously described 
#    - Optionally add long only trade strategies for all unique trade assets in the
#      portfolio 
#           - (Dow, Nasdaq, and S&P 500 for this portfolio) in this example
#           - Might be useful for bench marking trade strategies
#    - Each set has one Investment Portfolio Manager
#       - portfolio funds allocated per portfolio policy rules and re-balanced (if defined), 
#         across all trade strategies


portf_registered_obj = PortfolioRegisterItem(\
                            name                 = "Portfolio B, US-Indexes using LSTM and Long strategies",
                            taRegisterItems      = taRegisterItems,
                            portfolioInvMngObj   = portfInvMng,
                            tradingExecutionType = TradingAssetExecutionType.Simulation,
                            add_long_only_ts     = True )
2021-10-28 14:05:10,530 [INFO] root: *** Adding long only trade strategies for : {'^GSPC', '^IXIC', '^DJI'}
Persist to DB (optional)
In [48]:
session.add( portf_registered_obj )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")
 done
Re-Store from DB (optional)
In [49]:
session.expunge_all()
del portf_registered_obj

for tsObj in session.query(PortfolioRegisterItem):  
    print(tsObj.name)
    if  tsObj.name  == "Portfolio B, US-Indexes using LSTM and Long strategies" :
        break

portf_registered_obj = tsObj
print(portf_registered_obj.id, portf_registered_obj.name)
2021-10-28 14:05:21,930 [INFO] root: PortfolioRegisterItem init called. 
2021-10-28 14:05:21,930 [INFO] root: PortfolioRegisterItem init called. 
Portfolio of US-Indexes using SMA and Long strategies
Portfolio of US-Indexes using LSTM and Long strategies
2 Portfolio of US-Indexes using LSTM and Long strategies
Training, Validation and Test Periods for Backtest

In Order to backtest a trade strategy or portfolio that has AI models, the following data is required:

  1. Training Date Range

    1. Date range that will be used to train the AI models in the backtest
  2. Validation Date Range

    1. Date range that twill be used to validate the AI models, should not overlapped with the training date range
  3. Test Period Date Range

    1. This is the out-sample date range, which corresponds to the date range of the backtest

Date Ranges are defined with a DatasetDef object, and have the following parameters:

  1. strBegDateAIModels : Date to begin training or validation of an AI model
  2. strBegDate : Date to begin the backtest
  3. strEndDate : Date to end training, validation and Backtest

Note:

  1. The param strBegDateAIModels can be defined as the same date as strBegDate, that is the default, if not defined.
  2. The critical aspect of using this parameter is in the backtest. Some AI Models, such as time series, others using moving averages over many periods, create params with no predicting data for those initial dates. Thus, in order to ensure the backtest starts on the actual date specified, the strBegDateAIModels should be defined as an earlier date, and it should not overlapped with the validation period end-date to avoid any chance of bias by picking at the validation data.
In [50]:
training_period = DatasetDef(datasetType = DatasetType.Training,
                             strBegDateAIModels = "2000-07-01",
                             strBegDate         = "2001-01-01",
                             strEndDate         = "2005-12-30" )

validation_period = DatasetDef(datasetType = DatasetType.Validation,
                               strBegDateAIModels = "2005-07-01",
                               strBegDate         = "2006-01-01",
                               strEndDate         = "2007-06-30" )

testing_period = DatasetDef(datasetType = DatasetType.Testing,
                               strBegDateAIModels = "2007-07-01",
                               strBegDate         = "2008-01-01",
                               strEndDate         = "2008-12-31" )

fit_datasets = FitDatasetsDef( trainingDataset    = training_period,
                               validationDataset  = validation_period )
Execute Backtest
In [51]:
tsExecuteEngine = BacktestExecution( \
                    name = "Backtest for LSTM based Trade Strategies",
                    timePeriod  = testing_period,
                    fitDatasets = fit_datasets,
                    trade_asset_registered_item = portf_registered_obj )
In [ ]:
tsExecuteEngine.evaluate()
Backtest Metrics
Execution & Investment Metrics
In [53]:
tsExecuteEngine.getExecutionMetrics()
Out[53]:
TA_Reg_Name TA_Reg_Id Inv_Mng_Id Inv_Mng_Parent_Id Is_Portfolio Num_Trades_Executing Num_Trades_Completed Init_Capital Final_Capital Final_Inv_Capital Cum_Return Backtest_Status
0 Portfolio of US-Indexes using LSTM and Long st... 2 2 NaN Yes 0 103 12000000.0 1.366645e+07 0.0 0.138871 Completed
1 TA - LSTM for: ^DJI 7 7 2.0 No 0 45 2000000.0 3.635315e+06 0.0 0.817657 Completed
2 TA - LSTM for: ^IXIC 8 8 2.0 No 0 50 2000000.0 4.760641e+06 0.0 1.380321 Completed
3 TA - LSTM for: ^GSPC 9 9 2.0 No 0 5 2000000.0 1.466085e+06 0.0 -0.266957 Completed
4 Long-Only Trade Strategy for ^GSPC 10 10 2.0 No 0 1 2000000.0 1.248316e+06 0.0 -0.375842 Completed
5 Long-Only Trade Strategy for ^IXIC 11 11 2.0 No 0 1 2000000.0 1.209029e+06 0.0 -0.395486 Completed
6 Long-Only Trade Strategy for ^DJI 12 12 2.0 No 0 1 2000000.0 1.347062e+06 0.0 -0.326469 Completed
Performance Metrics
In [54]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ]
Out[54]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
0 Portfolio of US-Indexes using LSTM and Long st... Yes 2008-01-03 2008-12-31 1.0 0.14 0.14 0.57 -0.23 0.11 -0.07
1 TA - LSTM for: ^DJI No lstm ^DJI 2008-01-03 2008-12-31 1.0 0.82 0.82 1.76 -0.22 0.11 -0.08
2 TA - LSTM for: ^IXIC No lstm ^IXIC 2008-01-03 2008-12-31 1.0 1.38 1.39 2.31 -0.21 0.12 -0.07
3 TA - LSTM for: ^GSPC No lstm ^GSPC 2008-01-03 2008-12-31 1.0 -0.27 -0.27 -0.55 -0.48 0.12 -0.09
4 Long-Only Trade Strategy for ^GSPC No long ^GSPC 2008-01-03 2008-12-31 1.0 -0.38 -0.38 -0.94 -0.48 0.12 -0.09
5 Long-Only Trade Strategy for ^IXIC No long ^IXIC 2008-01-03 2008-12-31 1.0 -0.4 -0.4 -1.02 -0.49 0.12 -0.09
6 Long-Only Trade Strategy for ^DJI No long ^DJI 2008-01-03 2008-12-31 1.0 -0.33 -0.33 -0.86 -0.42 0.11 -0.08
In [55]:
tsExecuteEngine.getSummaryMetrics().T.head(60)
Out[55]:
0 1 2 3 4 5 6
ta_reg_item_name Portfolio of US-Indexes using LSTM and Long st... TA - LSTM for: ^DJI TA - LSTM for: ^IXIC TA - LSTM for: ^GSPC Long-Only Trade Strategy for ^GSPC Long-Only Trade Strategy for ^IXIC Long-Only Trade Strategy for ^DJI
ta_reg_item_id 2 7 8 9 10 11 12
is_portfolio Yes No No No No No No
model_type lstm lstm lstm long long long
trade_asset ^DJI ^IXIC ^GSPC ^GSPC ^IXIC ^DJI
test_period_len_days 365 365 365 365 365 365 365
tr_period_len_days 1824 1824 1824 1824 1824 1824 1824
val_period_len_days 545 545 545 545 545 545 545
index Strategy Strategy Strategy Strategy Strategy Strategy Strategy
Start Period 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03
End Period 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31
Risk-Free Rate 0.0 0.0 0.0 0.0 0.0 0.0 0.0
Time in Market 1.0 1.0 1.0 1.0 1.0 1.0 1.0
Cumulative Return 0.14 0.82 1.38 -0.27 -0.38 -0.4 -0.33
CAGR% 0.14 0.82 1.39 -0.27 -0.38 -0.4 -0.33
Sharpe 0.57 1.76 2.31 -0.55 -0.94 -1.02 -0.86
Sortino 0.93 2.98 4.08 -0.79 -1.29 -1.4 -1.2
Sortino/√2 0.66 2.11 2.88 -0.56 -0.91 -0.99 -0.85
Max Drawdown -0.23 -0.22 -0.21 -0.48 -0.48 -0.49 -0.42
Longest DD Days 118 63 54 362 362 362 240
Volatility (ann.) 0.31 0.38 0.41 0.41 0.41 0.41 0.38
Calmar 0.62 3.73 6.52 -0.56 -0.79 -0.8 -0.78
Skew 1.3 0.75 0.81 0.45 0.18 0.21 0.43
Kurtosis 8.97 3.92 2.76 4.01 3.99 3.22 4.22
Expected Daily % 0.0 0.0 0.0 -0.0 -0.0 -0.0 -0.0
Expected Monthly % 0.01 0.05 0.07 -0.03 -0.04 -0.04 -0.03
Expected Yearly % 0.14 0.82 1.38 -0.27 -0.38 -0.4 -0.33
Kelly Criterion 0.06 0.15 0.19 -0.06 -0.1 -0.09 -0.08
Risk of Ruin 0.0 0.0 0.0 0.0 0.0 0.0 0.0
Daily Value-at-Risk -0.03 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04
Expected Shortfall (cVaR) -0.03 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04
Gain/Pain Ratio 0.14 0.39 0.52 -0.1 -0.16 -0.17 -0.15
Gain/Pain (1M) 0.87 4.82 13.96 -0.46 -0.81 -0.69 -0.82
Payoff Ratio 1.19 1.22 1.23 0.88 0.83 0.96 0.92
Profit Factor 1.14 1.39 1.52 0.9 0.84 0.83 0.85
Common Sense Ratio 1.52 1.81 2.02 0.89 0.76 0.77 0.74
CPC Index 0.66 0.9 1.03 0.4 0.35 0.37 0.38
Tail Ratio 1.34 1.31 1.33 0.99 0.91 0.92 0.86
Outlier Win Ratio 5.22 4.35 4.62 4.92 4.26 3.61 4.23
Outlier Loss Ratio 5.51 3.65 3.27 3.85 4.3 4.04 4.23
MTD 0.2 0.3 0.31 0.21 0.01 0.03 -0.01
3M 0.08 0.19 0.39 -0.04 -0.18 -0.2 -0.15
6M 0.18 0.81 0.86 -0.17 -0.29 -0.31 -0.23
YTD 0.14 0.82 1.38 -0.27 -0.38 -0.4 -0.33
1Y 0.14 0.82 1.38 -0.27 -0.38 -0.4 -0.33
3Y (ann.) 0.14 0.82 1.39 -0.27 -0.38 -0.4 -0.33
5Y (ann.) 0.14 0.82 1.39 -0.27 -0.38 -0.4 -0.33
10Y (ann.) 0.14 0.82 1.39 -0.27 -0.38 -0.4 -0.33
All-time (ann.) 0.14 0.82 1.39 -0.27 -0.38 -0.4 -0.33
Best Day 0.11 0.11 0.12 0.12 0.12 0.12 0.11
Worst Day -0.07 -0.08 -0.07 -0.09 -0.09 -0.09 -0.08
Best Month 0.2 0.3 0.31 0.21 0.05 0.06 0.05
Worst Month -0.08 -0.1 -0.06 -0.17 -0.17 -0.18 -0.14
Best Year 0.14 0.82 1.38 -0.27 -0.38 -0.4 -0.33
Worst Year 0.14 0.82 1.38 -0.27 -0.38 -0.4 -0.33
Avg. Drawdown -0.04 -0.04 -0.04 -0.48 -0.48 -0.49 -0.26
Avg. Drawdown Days 28 18 9 362 362 362 180
Recovery Factor 0.61 3.7 6.46 -0.56 -0.78 -0.8 -0.78
Ulcer Index 3.4 1.8 1.46 inf inf 1.56 1.86
Avg. Up Month 0.06 0.11 0.12 0.07 0.02 0.03 0.02
Persist Backtest to DB (optional )
In [56]:
session.add( tsExecuteEngine )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")
 done
Re-Store Backtest
In [57]:
session.expunge_all()
del tsExecuteEngine

for tsObj in session.query(BacktestExecution):  
    print(tsObj.name)
    if  tsObj.name  == "Backtest for LSTM based Trade Strategies" :
        break

tsExecuteEngine = tsObj
print(tsExecuteEngine.id, tsExecuteEngine.name)
2021-10-28 14:10:27,670 [INFO] root: BacktestExecution init called. 
2021-10-28 14:10:27,676 [INFO] root: PortfolioRegisterItem init called. 
2021-10-28 14:10:27,677 [INFO] root: Loaded TradingAssetRegisterBase object
2021-10-28 14:10:27,683 [INFO] root: BacktestExecutionDatasets init called. 
2021-10-28 14:10:27,684 [INFO] root: BacktestExecution init called. 
2021-10-28 14:10:27,690 [INFO] root: PortfolioRegisterItem init called. 
2021-10-28 14:10:27,691 [INFO] root: Loaded TradingAssetRegisterBase object
2021-10-28 14:10:27,697 [INFO] root: BacktestExecutionDatasets init called. 
Backtest for SMA based Trade Strategies
Backtest for LSTM based Trade Strategies
2 Backtest for LSTM based Trade Strategies
In [58]:
tsExecuteEngine.getExecutionMetrics()
2021-10-28 14:10:31,759 [INFO] root: PortfolioInvMng init called. 
2021-10-28 14:10:31,760 [INFO] root: PortfolioInvMng init called. 
2021-10-28 14:10:31,777 [INFO] root: TradingAssetRegisterItem init called. 
2021-10-28 14:10:31,778 [INFO] root: TradingAssetRegisterItem init called. 
2021-10-28 14:10:31,779 [INFO] root: TradingAssetRegisterItem init called. 
2021-10-28 14:10:31,780 [INFO] root: TradingAssetRegisterItem init called. 
2021-10-28 14:10:31,780 [INFO] root: TradingAssetRegisterItem init called. 
2021-10-28 14:10:31,781 [INFO] root: TradingAssetRegisterItem init called. 
**** TradingAssetInvMngBase init called. 
2021-10-28 14:10:31,787 [INFO] root: TradingAssetInvMngBase init called. 
**** TradingAssetInvMngBase init called. 
2021-10-28 14:10:31,809 [INFO] root: TradingAssetInvMngBase init called. 
**** TradingAssetInvMngBase init called. 
2021-10-28 14:10:31,830 [INFO] root: TradingAssetInvMngBase init called. 
**** TradingAssetInvMngBase init called. 
2021-10-28 14:10:31,848 [INFO] root: TradingAssetInvMngBase init called. 
**** TradingAssetInvMngBase init called. 
2021-10-28 14:10:31,865 [INFO] root: TradingAssetInvMngBase init called. 
**** TradingAssetInvMngBase init called. 
2021-10-28 14:10:31,882 [INFO] root: TradingAssetInvMngBase init called. 
/Users/gustavozambrana/venvs/CFRM505/lib/python3.7/site-packages/sqlalchemy/orm/loading.py:628: SAWarning: Loading context for <PortfolioInvMng at 0x7f9c46745910> has changed within a load/refresh handler, suggesting a row refresh operation took place. If this event handler is expected to be emitting row refresh operations within an existing load or refresh operation, set restore_load_context=True when establishing the listener to ensure the context remains unchanged when the event handler completes.
  "handler completes." % (state_str(state),)
Out[58]:
TA_Reg_Name TA_Reg_Id Inv_Mng_Id Inv_Mng_Parent_Id Is_Portfolio Num_Trades_Executing Num_Trades_Completed Init_Capital Final_Capital Final_Inv_Capital Cum_Return Backtest_Status
0 Portfolio of US-Indexes using LSTM and Long st... 2 2 NaN Yes 0 103 12000000.0 1.366645e+07 0.0 0.138871 Completed
1 TA - LSTM for: ^DJI 7 7 2.0 No 0 45 2000000.0 3.635315e+06 0.0 0.817657 Completed
2 TA - LSTM for: ^IXIC 8 8 2.0 No 0 50 2000000.0 4.760641e+06 0.0 1.380321 Completed
3 TA - LSTM for: ^GSPC 9 9 2.0 No 0 5 2000000.0 1.466085e+06 0.0 -0.266957 Completed
4 Long-Only Trade Strategy for ^GSPC 10 10 2.0 No 0 1 2000000.0 1.248316e+06 0.0 -0.375842 Completed
5 Long-Only Trade Strategy for ^IXIC 11 11 2.0 No 0 1 2000000.0 1.209029e+06 0.0 -0.395486 Completed
6 Long-Only Trade Strategy for ^DJI 12 12 2.0 No 0 1 2000000.0 1.347062e+06 0.0 -0.326469 Completed
In [ ]:
 

Portfolio C

  1. Portfolio C: Long and Multiple Configured SMA Trade Strategies for US Indixes

    Description:

     1. Portfolio with 27 trading strategies
     2. $200,000/strategy, Total Budget = $5.4M
     3. No-Rebalance during the backtest 
     4. 100% capital invested
     5. Portfolio investment using equal weights for each trade strategy
    
    

    Trade Strategies:

     1. Three trade strategies: Nasdaq, S&P 500, and DOW Jones with buy-and-hold
     2. 21 trade strategies: Nasdaq, S&P 500, and DOW Jones using following SMA Configuration:
    
        sma-conf fast_mav, slow_mav, enter_if_last_nmatch, enter_if_cross_over_sig, exit_if_last_nmatch
             1       20       100          2                    True                     2
             2       10        50          2                    True                     2
             3       10        50          2                    True                     1
             4       15        60          2                    True                     2
             5       15        75          2                    True                     1
             6        7        35          2                    True                     2
             7        7        35          2                    True                     1               
    
     3. Three trade strategies: Nasdaq, S&P 500, and DOW Jones using the following configuration: 
    
         - A Composite SMA Trade Strategy based on the the first five SMA Configured trade strategies
           above
    
         - The Set Entry cofiguration rules are: 
           a. Majority Voting (default)
              Three of the Five SMA Indicators configured in the set must signaled the same type of
              investment decision.
           b. Enter a trade if the last n voting decisions are the same, set to 1 (default )
           c. Enter a trade if there is cross-over signaled after applying rules a) and b), 
              set to False (default)
    
         - The Set Exit configuration rules are: 
           a. Majority Voting (Default)
               - Exit a long trade if the percent of SMA Indicators signaling an exit for a long position
                  is greater that the percent signaling no-exit 
               - Exit a short trade if the percent of SMA Indicators signaling an exit for a short position
                  is greater that the percent signaling no-exit 
           b. Exit a trade if the last n exit decisions are the same, set to 1 (default )
    
     4. Three trade strategies: Nasdaq, S&P 500, and DOW Jones using the following configuration: 
    
         - A Composite SMA Trade Strategy based on all the SMA Configured trade strategies
    
         - The Set Entry cofiguration rules are: 
           a. Voting Percent
              The majority of the signals indicating an investment position (either short or long), 
              must also meet a minimum percent of 50% across all the strategies in the set.
           b. Enter a trade if the last n voting decisions are the same, set to 1 (default )
           c. Enter a trade if there is cross-over signaled after applying rules a) and b), 
              set to False (default)
    
         - The Set Exit configuration rules are: 
           a. Majority Voting (Default)
               - Exit a long trade if the percent of SMA Indicators signaling an exit for a long position
                  is greater that the percent signaling no-exit 
               - Exit a short trade if the percent of SMA Indicators signaling an exit for a short position
                  is greater that the percent signaling no-exit 
           b. Exit a trade if the last n exit decisions are the same, set to 1 (default )
    
    

    Backtest:

     1. Type: regular
     2. Test Period: 
         1. Begin Date = 2001-01-01 
         2. End Date   = 2001-12-31 
Portfolio Trade Assets
In [72]:
portfolio_trade_assets   = [ "^DJI", "^IXIC", "^GSPC" ]
Market Data Manager
In [73]:
dirPathMarketData = '/Users/gustavozambrana/Google Drive/Python/Projects/Trade_Engine/Data/US_Market_Indixes'

supportedTradeAssets   = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str           = "2000-01-01"
end_date_str           = None

ts_marketdat_mng = TradeStrategyMarketDataMng(\
        marketDataProviderName = "yahoofinance",
        supportedTradeAssets   = supportedTradeAssets,
        stock_price_col_name   = "Adj Close",
        fileNameMarketData     = "US_Indixes_And_ETFs_MrkData",
        dirPathMarketData      = dirPathMarketData,
        beg_date_str           = beg_date_str,
        end_date_str           = end_date_str,
        interval               = "1d"  ) 
2021-10-28 15:21:44,809 [INFO] root: Found previous Market data previously loaded to specified file and dir.
Simulation Broker
In [74]:
brokerTradingObj = SimBrokerTrading()
Trade Strategies, Trade Investment Manager, and Trade Asset Register Items
In [75]:
tsConfDat = TradeStrategyConfigData()

# Set Config

tsConfDat.tsSetConfig(\
    ts_set_conf_dict = 
           { 'set_actions_conf' : 
                      { "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
                        "exit"  : { 'votingPolicy' : 1, 
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1 } 
                      }
           } )
           
# TS #1

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_1",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 20, 'win_slow' : 100 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : True },
                                  'exit_policy_args'   : { 'lastn_match' : 2 } },
                             },
                    }  )

# TS #2

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_2",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 10, 'win_slow' : 50 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : True },
                                  'exit_policy_args'   : { 'lastn_match' : 2 } },
                             },
                    }  )

# TS #3

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_3",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 10, 'win_slow' : 50 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : True },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },
                             },
                    }  )

# TS #4

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_4",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 15, 'win_slow' : 60 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : True },
                                  'exit_policy_args'   : { 'lastn_match' : 2 } },
                             },
                    }  )

# TS #5

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_5",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 15, 'win_slow' : 75 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : True },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },
                             },
                    }  )

# TS #6

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_6",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 7, 'win_slow' : 35 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : True },
                                  'exit_policy_args'   : { 'lastn_match' : 2 } },
                             },
                    }  )

# TS #7

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_7",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 7, 'win_slow' : 35 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : True },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },
                             },
                    }  )
In [76]:
taRegisterItems = [ ]
tsActionGen = TradeStrategyActionGenerator()

for trade_asset in portfolio_trade_assets :
    
    num_ts = len(tsConfDat.name_list) + 1  # adding the composite  trade strategy
    
    for i in range( num_ts ) :

        if i <= num_ts - 2:
            # *** Trade Strategy 

            actionDatItem  = tsConfDat.getTSConfigDataForItem(item_num = i )
            ts_unique_name = actionDatItem.name_list[0]
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = actionDatItem,
                                                     pipelineMng       = None )
        else :
            # Composite Trade Strategy 
            
            ts_unique_name = "all"            
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = tsConfDat,
                                                     pipelineMng       = None )

        ts_model = TradeStrategyBaseModelPersist(\
                        trade_asset               = trade_asset,
                        ts_marketdat_mng          = ts_marketdat_mng,
                        ts_enter                  = trade_enter_set,
                        ts_exit                   = trade_exit_set,                       
                        model_type                = ts_unique_name,
                        model_version             = "1.0",
                        market_data_period        = MarketDataPeriod.Day,
                    ) 

        # *** Trade Strategy Investment Manager 

        taInvMng = TradingAssetInvMngBase(\
                                        trade_asset                = trade_asset,
                                        minPeriodsBetweenTrades    = 1,
                                        initInvestment             = 1000000.0, 
                                        capPercentToInvestPerTrade = 100.0,
                                        minInvestPercent           = 5.0,
                                        min_account_balance        = 1000.0 )

        # *** Trade Register Item
        # *** This object has all configuration defined to execute a given trade strategy,
        # *** It can be executed individually in backtest or as part of a portfolio

        ta_registered_item = TradingAssetRegisterItem(\
                trade_name                    = "{0}_{1}".format(ts_unique_name, trade_asset), 
                ts_model                      = ts_model,
                tradingExecutionType          = TradingAssetExecutionType.Simulation,
                tradingBrokerObj              = brokerTradingObj,
                tradingAssetInvMngObj         = taInvMng )  

        taRegisterItems.append(ta_registered_item)
In [77]:
print("Number of configured Trade Asset Register Items: ", len(taRegisterItems) )
Number of configured Trade Asset Register Items:  24
Portfolio Investment Manager
In [78]:
# *** Porttfolio Investment Manager across all individual trade strategies investment managers
# *** Role: 
# ***    1) Managed investment funds across n number of trade strategies
# ***    2) Rebalance portfolio periodically or never
# ***    3) Portfolio Policy Weights 
# ***          equal weights (default)
# ***          MinimumVariance
# ***          User defined 
# ***    4) Track Portfolio level returns and metrics
# ***          Individual Trade Strategies return and metrics tracked through their 
# ***          investment managers
# ***          Portfolio funds are split across each trade strategy investment manager based on the
# ***          portfolio weights

portfInvMng = PortfolioInvMng(\
                  name                       = "Portfolio Inv. Manager for US-Indexes - Multiple-SMA TS",
                  initInvestment             = 2000000.0 * ( len(taRegisterItems) + 3),  # 200K/trade-strag
                  portfRebalanceFreq         = PortfolioRebalanceFrequency.Never,
                  portfRebalancePeriods      = 1,
                  minInvestPercent           = 5.0,
                  min_account_balance        = 1000.0,     
                  minPeriodsBetweenTrades    = 1,
                  capPercentToInvestPerTrade = 100.0 )
Trade Register Items Portfolio
In [79]:
# *** Set of Trade Register Items
#
# Configuration Summary:
#    - Each set has 1 to n trade register items as previously described 
#    - Optionally add long only trade strategies for all unique trade assets in the
#      portfolio 
#           - (Dow, Nasdaq, and S&P 500 for this portfolio) in this example
#           - Might be useful for bench marking trade strategies
#    - Each set has one Investment Portfolio Manager
#       - portfolio funds allocated per portfolio policy rules and re-balanced (if defined), 
#         across all trade strategies


portf_registered_obj = PortfolioRegisterItem(\
                        name                 = "Portfolio C, US-Indexes with Multiple-SMA and Long strategies",
                        taRegisterItems      = taRegisterItems,
                        portfolioInvMngObj   = portfInvMng,
                        tradingExecutionType = TradingAssetExecutionType.Simulation,
                        add_long_only_ts     = True )
2021-10-28 15:22:00,268 [INFO] root: *** Adding long only trade strategies for : {'^GSPC', '^IXIC', '^DJI'}
Persist to DB (optional)
In [68]:
session.add( portf_registered_obj )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")
 done
Re-Store from DB (optional)
In [69]:
session.expunge_all()
del portf_registered_obj

for tsObj in session.query(PortfolioRegisterItem):  
    print(tsObj.name)
    if  tsObj.name  == "Portfolio C, US-Indexes with Multiple-SMA and Long strategies" :
        break

portf_registered_obj = tsObj
print(portf_registered_obj.id, portf_registered_obj.name)
2021-10-28 15:20:44,078 [INFO] root: PortfolioRegisterItem init called. 
2021-10-28 15:20:44,078 [INFO] root: PortfolioRegisterItem init called. 
2021-10-28 15:20:44,079 [INFO] root: PortfolioRegisterItem init called. 
Portfolio of US-Indexes using SMA and Long strategies
1 Portfolio of US-Indexes using SMA and Long strategies
Execute Backtest
In [80]:
tsExecuteEngine = BacktestExecution( \
                    name = "Backtest for Portfolio of Multiple-SMA based Trade Strategies",
                    timePeriod = DatasetDef(datasetType = DatasetType.Testing,
                                            strBegDate = "2001-01-01", 
                                            strEndDate = "2001-12-31" ),
                    trade_asset_registered_item = portf_registered_obj )
In [ ]:
tsExecuteEngine.evaluate()
Backtest Metrics
Execution & Investment Metrics
In [82]:
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
        'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']]
Out[82]:
TA_Reg_Name Is_Portfolio Num_Trades_Completed Init_Capital Final_Capital Cum_Return Backtest_Status
0 Portfolio of US-Indexes with Multiple-SMA and ... Yes 158 54000000.0 5.772265e+07 0.068938 Completed
1 ts_sma_1_^DJI No 6 2000000.0 1.918609e+06 -0.040696 Completed
2 ts_sma_2_^DJI No 7 2000000.0 2.170411e+06 0.085205 Completed
3 ts_sma_3_^DJI No 7 2000000.0 2.218299e+06 0.109149 Completed
4 ts_sma_4_^DJI No 7 2000000.0 1.842030e+06 -0.078985 Completed
5 ts_sma_5_^DJI No 5 2000000.0 1.895885e+06 -0.052058 Completed
6 ts_sma_6_^DJI No 7 2000000.0 2.156208e+06 0.078104 Completed
7 ts_sma_7_^DJI No 7 2000000.0 2.227205e+06 0.113602 Completed
8 all_^DJI No 7 2000000.0 2.187996e+06 0.093998 Completed
9 ts_sma_1_^IXIC No 8 2000000.0 2.140912e+06 0.070456 Completed
10 ts_sma_2_^IXIC No 6 2000000.0 2.443404e+06 0.221702 Completed
11 ts_sma_3_^IXIC No 6 2000000.0 2.401716e+06 0.200858 Completed
12 ts_sma_4_^IXIC No 6 2000000.0 2.551934e+06 0.275967 Completed
13 ts_sma_5_^IXIC No 4 2000000.0 2.126019e+06 0.063009 Completed
14 ts_sma_6_^IXIC No 8 2000000.0 2.202711e+06 0.101356 Completed
15 ts_sma_7_^IXIC No 8 2000000.0 2.168078e+06 0.084039 Completed
16 all_^IXIC No 6 2000000.0 2.336705e+06 0.168352 Completed
17 ts_sma_1_^GSPC No 4 2000000.0 2.023192e+06 0.011596 Completed
18 ts_sma_2_^GSPC No 6 2000000.0 2.208141e+06 0.104071 Completed
19 ts_sma_3_^GSPC No 6 2000000.0 2.256189e+06 0.128095 Completed
20 ts_sma_4_^GSPC No 6 2000000.0 1.903230e+06 -0.048385 Completed
21 ts_sma_5_^GSPC No 6 2000000.0 2.048397e+06 0.024198 Completed
22 ts_sma_6_^GSPC No 8 2000000.0 2.331342e+06 0.165671 Completed
23 ts_sma_7_^GSPC No 8 2000000.0 2.334666e+06 0.167333 Completed
24 all_^GSPC No 6 2000000.0 2.254545e+06 0.127272 Completed
25 Long-Only Trade Strategy for ^GSPC No 1 2000000.0 1.789374e+06 -0.105313 Completed
26 Long-Only Trade Strategy for ^IXIC No 1 2000000.0 1.702247e+06 -0.148877 Completed
27 Long-Only Trade Strategy for ^DJI No 1 2000000.0 1.883204e+06 -0.058398 Completed
Performance Metrics
In [83]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ]
Out[83]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
0 Portfolio of US-Indexes with Multiple-SMA and ... Yes 2001-01-03 2001-12-31 1.0 0.07 0.07 0.52 -0.12 0.04 -0.03
1 ts_sma_1_^DJI No ts_sma_1 ^DJI 2001-01-03 2001-12-31 1.0 -0.04 -0.04 -0.13 -0.19 0.06 -0.04
2 ts_sma_2_^DJI No ts_sma_2 ^DJI 2001-01-03 2001-12-31 1.0 0.09 0.09 0.54 -0.12 0.06 -0.04
3 ts_sma_3_^DJI No ts_sma_3 ^DJI 2001-01-03 2001-12-31 0.97 0.11 0.11 0.66 -0.11 0.06 -0.04
4 ts_sma_4_^DJI No ts_sma_4 ^DJI 2001-01-03 2001-12-31 1.0 -0.08 -0.08 -0.35 -0.15 0.06 -0.04
5 ts_sma_5_^DJI No ts_sma_5 ^DJI 2001-01-03 2001-12-31 0.98 -0.05 -0.05 -0.19 -0.19 0.06 -0.04
6 ts_sma_6_^DJI No ts_sma_6 ^DJI 2001-01-03 2001-12-31 1.0 0.08 0.08 0.5 -0.14 0.06 -0.04
7 ts_sma_7_^DJI No ts_sma_7 ^DJI 2001-01-03 2001-12-31 0.97 0.11 0.11 0.67 -0.13 0.06 -0.04
8 all_^DJI No all ^DJI 2001-01-03 2001-12-31 0.99 0.09 0.09 0.58 -0.12 0.06 -0.04
9 ts_sma_1_^IXIC No ts_sma_1 ^IXIC 2001-01-03 2001-12-31 1.0 0.07 0.07 0.38 -0.28 0.06 -0.05
10 ts_sma_2_^IXIC No ts_sma_2 ^IXIC 2001-01-03 2001-12-31 1.0 0.22 0.22 0.78 -0.25 0.06 -0.05
11 ts_sma_3_^IXIC No ts_sma_3 ^IXIC 2001-01-03 2001-12-31 0.98 0.2 0.2 0.73 -0.26 0.06 -0.05
12 ts_sma_4_^IXIC No ts_sma_4 ^IXIC 2001-01-03 2001-12-31 1.0 0.28 0.28 0.93 -0.23 0.06 -0.05
13 ts_sma_5_^IXIC No ts_sma_5 ^IXIC 2001-01-03 2001-12-31 0.66 0.06 0.06 0.36 -0.26 0.06 -0.05
14 ts_sma_6_^IXIC No ts_sma_6 ^IXIC 2001-01-03 2001-12-31 1.0 0.1 0.1 0.46 -0.3 0.06 -0.05
15 ts_sma_7_^IXIC No ts_sma_7 ^IXIC 2001-01-03 2001-12-31 0.97 0.08 0.08 0.41 -0.29 0.06 -0.05
16 all_^IXIC No all ^IXIC 2001-01-03 2001-12-31 1.0 0.17 0.17 0.64 -0.28 0.06 -0.05
17 ts_sma_1_^GSPC No ts_sma_1 ^GSPC 2001-01-03 2001-12-31 1.0 0.01 0.01 0.15 -0.22 0.04 -0.03
18 ts_sma_2_^GSPC No ts_sma_2 ^GSPC 2001-01-03 2001-12-31 1.0 0.1 0.1 0.65 -0.11 0.04 -0.03
19 ts_sma_3_^GSPC No ts_sma_3 ^GSPC 2001-01-03 2001-12-31 0.98 0.13 0.13 0.77 -0.11 0.04 -0.03
20 ts_sma_4_^GSPC No ts_sma_4 ^GSPC 2001-01-03 2001-12-31 1.0 -0.05 -0.05 -0.18 -0.16 0.04 -0.04
21 ts_sma_5_^GSPC No ts_sma_5 ^GSPC 2001-01-03 2001-12-31 0.98 0.02 0.02 0.22 -0.15 0.04 -0.03
22 ts_sma_6_^GSPC No ts_sma_6 ^GSPC 2001-01-03 2001-12-31 1.0 0.17 0.17 0.93 -0.14 0.04 -0.03
23 ts_sma_7_^GSPC No ts_sma_7 ^GSPC 2001-01-03 2001-12-31 0.95 0.17 0.17 0.95 -0.12 0.04 -0.03
24 all_^GSPC No all ^GSPC 2001-01-03 2001-12-31 1.0 0.13 0.13 0.77 -0.11 0.04 -0.03
25 Long-Only Trade Strategy for ^GSPC No long ^GSPC 2001-01-03 2001-12-31 1.0 -0.11 -0.11 -0.42 -0.3 0.05 -0.05
26 Long-Only Trade Strategy for ^IXIC No long ^IXIC 2001-01-03 2001-12-31 1.0 -0.15 -0.15 -0.17 -0.5 0.14 -0.07
27 Long-Only Trade Strategy for ^DJI No long ^DJI 2001-01-03 2001-12-31 1.0 -0.06 -0.06 -0.18 -0.27 0.04 -0.07
In [84]:
tsExecuteEngine.getSummaryMetrics().T.head(60)
Out[84]:
0 1 2 3 4 5 6 7 8 9 ... 18 19 20 21 22 23 24 25 26 27
ta_reg_item_name Portfolio of US-Indexes with Multiple-SMA and ... ts_sma_1_^DJI ts_sma_2_^DJI ts_sma_3_^DJI ts_sma_4_^DJI ts_sma_5_^DJI ts_sma_6_^DJI ts_sma_7_^DJI all_^DJI ts_sma_1_^IXIC ... ts_sma_2_^GSPC ts_sma_3_^GSPC ts_sma_4_^GSPC ts_sma_5_^GSPC ts_sma_6_^GSPC ts_sma_7_^GSPC all_^GSPC Long-Only Trade Strategy for ^GSPC Long-Only Trade Strategy for ^IXIC Long-Only Trade Strategy for ^DJI
ta_reg_item_id None None None None None None None None None None ... None None None None None None None None None None
is_portfolio Yes No No No No No No No No No ... No No No No No No No No No No
model_type ts_sma_1 ts_sma_2 ts_sma_3 ts_sma_4 ts_sma_5 ts_sma_6 ts_sma_7 all ts_sma_1 ... ts_sma_2 ts_sma_3 ts_sma_4 ts_sma_5 ts_sma_6 ts_sma_7 all long long long
trade_asset ^DJI ^DJI ^DJI ^DJI ^DJI ^DJI ^DJI ^DJI ^IXIC ... ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^IXIC ^DJI
test_period_len_days 364 364 364 364 364 364 364 364 364 364 ... 364 364 364 364 364 364 364 364 364 364
tr_period_len_days 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
val_period_len_days 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
index Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy ... Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy
Start Period 2001-01-03 2001-01-03 2001-01-03 2001-01-03 2001-01-03 2001-01-03 2001-01-03 2001-01-03 2001-01-03 2001-01-03 ... 2001-01-03 2001-01-03 2001-01-03 2001-01-03 2001-01-03 2001-01-03 2001-01-03 2001-01-03 2001-01-03 2001-01-03
End Period 2001-12-31 2001-12-31 2001-12-31 2001-12-31 2001-12-31 2001-12-31 2001-12-31 2001-12-31 2001-12-31 2001-12-31 ... 2001-12-31 2001-12-31 2001-12-31 2001-12-31 2001-12-31 2001-12-31 2001-12-31 2001-12-31 2001-12-31 2001-12-31
Risk-Free Rate 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
Time in Market 1.0 1.0 1.0 0.97 1.0 0.98 1.0 0.97 0.99 1.0 ... 1.0 0.98 1.0 0.98 1.0 0.95 1.0 1.0 1.0 1.0
Cumulative Return 0.07 -0.04 0.09 0.11 -0.08 -0.05 0.08 0.11 0.09 0.07 ... 0.1 0.13 -0.05 0.02 0.17 0.17 0.13 -0.11 -0.15 -0.06
CAGR% 0.07 -0.04 0.09 0.11 -0.08 -0.05 0.08 0.11 0.09 0.07 ... 0.1 0.13 -0.05 0.02 0.17 0.17 0.13 -0.11 -0.15 -0.06
Sharpe 0.52 -0.13 0.54 0.66 -0.35 -0.19 0.5 0.67 0.58 0.38 ... 0.65 0.77 -0.18 0.22 0.93 0.95 0.77 -0.42 -0.17 -0.18
Sortino 0.76 -0.19 0.84 1.04 -0.52 -0.29 0.76 1.04 0.91 0.56 ... 0.98 1.18 -0.26 0.34 1.43 1.47 1.18 -0.59 -0.25 -0.25
Sortino/√2 0.53 -0.13 0.59 0.74 -0.37 -0.21 0.54 0.73 0.64 0.4 ... 0.69 0.84 -0.19 0.24 1.01 1.04 0.83 -0.42 -0.18 -0.18
Max Drawdown -0.12 -0.19 -0.12 -0.11 -0.15 -0.19 -0.14 -0.13 -0.12 -0.28 ... -0.11 -0.11 -0.16 -0.15 -0.14 -0.12 -0.11 -0.3 -0.5 -0.27
Longest DD Days 167 181 160 168 259 283 256 178 167 270 ... 155 155 254 168 167 165 155 334 340 223
Volatility (ann.) 0.16 0.19 0.19 0.19 0.19 0.19 0.19 0.19 0.19 0.31 ... 0.18 0.18 0.19 0.18 0.19 0.18 0.18 0.21 0.43 0.21
Calmar 0.57 -0.22 0.69 0.98 -0.52 -0.27 0.56 0.91 0.81 0.25 ... 0.98 1.17 -0.3 0.16 1.24 1.4 1.21 -0.36 -0.3 -0.22
Skew 0.11 0.35 0.59 0.61 0.73 0.72 0.53 0.51 0.59 0.16 ... 0.26 0.27 0.33 0.35 0.24 0.26 0.28 0.1 0.65 -0.47
Kurtosis 1.3 2.84 2.61 2.78 2.93 3.14 2.5 2.56 2.62 -0.07 ... 0.56 0.65 0.79 0.65 0.48 0.65 0.51 1.59 2.92 3.72
Expected Daily % 0.0 -0.0 0.0 0.0 -0.0 -0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 -0.0 0.0 0.0 0.0 0.0 -0.0 -0.0 -0.0
Expected Monthly % 0.01 -0.0 0.01 0.01 -0.01 -0.0 0.01 0.01 0.01 0.01 ... 0.01 0.01 -0.0 0.0 0.01 0.01 0.01 -0.01 -0.01 -0.01
Expected Yearly % 0.07 -0.04 0.09 0.11 -0.08 -0.05 0.08 0.11 0.09 0.07 ... 0.1 0.13 -0.05 0.02 0.17 0.17 0.13 -0.11 -0.15 -0.06
Kelly Criterion 0.04 -0.01 0.04 0.05 -0.03 -0.02 0.04 0.05 0.05 0.03 ... 0.05 0.06 -0.01 0.02 0.07 0.08 0.06 -0.04 -0.01 -0.02
Risk of Ruin 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
Daily Value-at-Risk -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.03 ... -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.04 -0.02
Expected Shortfall (cVaR) -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.03 ... -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.04 -0.02
Gain/Pain Ratio 0.09 -0.02 0.09 0.12 -0.06 -0.03 0.09 0.12 0.1 0.06 ... 0.11 0.13 -0.03 0.04 0.16 0.17 0.13 -0.07 -0.03 -0.03
Gain/Pain (1M) 0.56 -0.1 0.68 0.99 -0.21 -0.12 0.4 0.62 0.78 0.24 ... 1.12 1.36 -0.13 0.19 1.21 1.33 1.34 -0.26 -0.1 -0.13
Payoff Ratio 1.0 0.96 1.07 1.09 1.14 1.08 1.1 1.07 1.07 1.08 ... 1.04 1.05 1.04 1.08 1.04 1.02 1.06 1.0 0.95 0.97
Profit Factor 1.09 0.98 1.09 1.12 0.94 0.97 1.09 1.12 1.1 1.06 ... 1.11 1.13 0.97 1.04 1.16 1.17 1.13 0.93 0.97 0.97
Common Sense Ratio 1.13 1.15 1.43 1.5 1.18 1.13 1.35 1.39 1.44 1.1 ... 1.27 1.38 1.08 1.21 1.33 1.36 1.38 0.93 0.94 0.96
CPC Index 0.57 0.47 0.59 0.62 0.49 0.49 0.59 0.61 0.6 0.57 ... 0.6 0.62 0.49 0.55 0.64 0.64 0.62 0.45 0.47 0.47
Tail Ratio 1.03 1.18 1.31 1.34 1.25 1.17 1.24 1.24 1.3 1.03 ... 1.15 1.22 1.11 1.17 1.14 1.16 1.22 1.0 0.97 0.99
Outlier Win Ratio 3.76 3.54 3.39 3.52 3.28 3.51 3.29 3.45 3.41 2.99 ... 3.06 3.17 3.12 3.07 2.97 3.24 3.02 3.82 3.6 3.67
Outlier Loss Ratio 3.11 3.53 2.95 2.99 3.06 3.0 3.26 3.19 2.95 2.77 ... 2.71 2.74 2.68 2.89 2.82 2.77 2.76 3.23 2.94 3.6
MTD 0.01 0.01 0.02 0.02 0.02 0.02 0.02 0.02 0.02 0.01 ... 0.01 0.01 0.01 0.01 0.01 0.0 0.01 0.01 0.01 0.02
3M -0.0 -0.07 -0.01 -0.01 -0.07 -0.07 0.06 0.06 -0.01 -0.17 ... -0.03 -0.02 -0.06 -0.08 0.04 0.02 -0.03 0.1 0.3 0.13
6M 0.12 0.08 0.14 0.14 0.08 0.03 0.22 0.22 0.14 -0.02 ... 0.11 0.13 0.08 0.03 0.17 0.13 0.11 -0.06 -0.1 -0.05
YTD 0.07 -0.04 0.09 0.11 -0.08 -0.05 0.08 0.11 0.09 0.07 ... 0.1 0.13 -0.05 0.02 0.17 0.17 0.13 -0.11 -0.15 -0.06
1Y 0.07 -0.04 0.09 0.11 -0.08 -0.05 0.08 0.11 0.09 0.07 ... 0.1 0.13 -0.05 0.02 0.17 0.17 0.13 -0.11 -0.15 -0.06
3Y (ann.) 0.07 -0.04 0.09 0.11 -0.08 -0.05 0.08 0.11 0.09 0.07 ... 0.1 0.13 -0.05 0.02 0.17 0.17 0.13 -0.11 -0.15 -0.06
5Y (ann.) 0.07 -0.04 0.09 0.11 -0.08 -0.05 0.08 0.11 0.09 0.07 ... 0.1 0.13 -0.05 0.02 0.17 0.17 0.13 -0.11 -0.15 -0.06
10Y (ann.) 0.07 -0.04 0.09 0.11 -0.08 -0.05 0.08 0.11 0.09 0.07 ... 0.1 0.13 -0.05 0.02 0.17 0.17 0.13 -0.11 -0.15 -0.06
All-time (ann.) 0.07 -0.04 0.09 0.11 -0.08 -0.05 0.08 0.11 0.09 0.07 ... 0.1 0.13 -0.05 0.02 0.17 0.17 0.13 -0.11 -0.15 -0.06
Best Day 0.04 0.06 0.06 0.06 0.06 0.06 0.06 0.06 0.06 0.06 ... 0.04 0.04 0.04 0.04 0.04 0.04 0.04 0.05 0.14 0.04
Worst Day -0.03 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.05 ... -0.03 -0.03 -0.04 -0.03 -0.03 -0.03 -0.03 -0.05 -0.07 -0.07
Best Month 0.08 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.25 ... 0.07 0.07 0.07 0.07 0.08 0.08 0.07 0.08 0.21 0.09
Worst Month -0.05 -0.08 -0.06 -0.03 -0.08 -0.08 -0.07 -0.06 -0.05 -0.11 ... -0.04 -0.04 -0.08 -0.07 -0.07 -0.06 -0.04 -0.09 -0.22 -0.11
Best Year 0.07 -0.04 0.09 0.11 -0.08 -0.05 0.08 0.11 0.09 0.07 ... 0.1 0.13 -0.05 0.02 0.17 0.17 0.13 -0.11 -0.15 -0.06
Worst Year 0.07 -0.04 0.09 0.11 -0.08 -0.05 0.08 0.11 0.09 0.07 ... 0.1 0.13 -0.05 0.02 0.17 0.17 0.13 -0.11 -0.15 -0.06
Avg. Drawdown -0.06 -0.09 -0.09 -0.08 -0.15 -0.06 -0.05 -0.06 -0.11 -0.07 ... -0.05 -0.05 -0.15 -0.06 -0.04 -0.04 -0.05 -0.09 -0.15 -0.15
Avg. Drawdown Days 69 69 85 84 178 71 58 49 114 37 ... 42 42 176 49 33 37 42 89 88 118
Recovery Factor 0.57 -0.21 0.69 0.97 -0.52 -0.27 0.56 0.9 0.81 0.25 ... 0.97 1.16 -0.3 0.16 1.23 1.39 1.2 -0.35 -0.3 -0.21
Ulcer Index 1.06 1.07 inf inf inf inf inf inf inf 1.04 ... 1.04 1.03 1.06 1.04 1.03 1.03 1.03 1.04 1.02 1.08
Avg. Up Month 0.04 0.04 0.04 0.05 0.05 0.05 0.05 0.05 0.04 0.1 ... 0.04 0.03 0.04 0.05 0.03 0.03 0.03 0.04 0.11 0.04

60 rows × 28 columns

Persist Backtest to DB (optional )
In [85]:
session.add( tsExecuteEngine )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst)
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")
 done

Portfolio D

  1. Portfolio D: Long and Multiple Configured LSTM Trade Strategies for US Indixes

    Description:

     1. Portfolio with 27 trading strategies
     2. $200,000/strategy, Total Budget = $5.4M
     3. No-Rebalance during the backtest 
     4. 100% capital invested
     5. Portfolio investment using equal weights for each trade strategy
    
    

    Trade Strategies:

     1. Three trade strategies: Nasdaq, S&P 500, and DOW Jones with buy-and-hold
     2. 21 trade strategies: Nasdaq, S&P 500, and DOW Jones using following LSTM Configurations:
    
                                                    LSTM Models
           Parameter                 #1      #2     #3       #4      #5      #6      #7
    
        epochs                       20      20     20       20      20      20      20
        no neurons layer 1           20      20     20       20      20      20      20
        no neurons layer 2           20      20     20       20      20      20      20
        time series length           20     100     50       50      40      30      60         
        no predictions ahead          3      15      5        5       3       3       5
        extend trade dyn            Yes     Yes    Yes      Yes     Yes     Yes     Yes
        re_evalaute_exit_dyn        Yes     Yes    Yes      Yes     Yes     Yes     Yes
        enter_if_last_nmatch          1       1      1        1       1       1       1
        enter_if_cross_over_sig      No      No     No       No      No      No      No
        exit_if_last_nmatch           1       1      1        2       1       1       1
    
     3. Three trade strategies: Nasdaq, S&P 500, and DOW Jones using the following Composite 
        model configuration: 
    
         - A Composite LSTM Trade Strategy based on all the LSTM configured trade strategies above
    
         - The Set Entry cofiguration rules are: 
           a. Majority Voting (default)
           b. Enter a trade if the last n voting decisions are the same, set to 1 (default )
           c. Enter a trade if there is cross-over signaled after applying rules a) and b), 
              set to False (default)
    
         - The Set Exit configuration rules are: 
           a. Majority Voting (Default)
               - Exit a long trade if the percent of LSTM Indicators signaling an exit for a long position
                  is greater that the percent signaling no-exit 
               - Exit a short trade if the percent of LSTM Indicators signaling an exit for a short position
                  is greater that the percent signaling no-exit 
           b. Exit a trade if the last n exit decisions are the same, set to 1 (default )
    
    

    Backtest:

     1. Type: regular
     2. AI Models Fit Date Ranges
         1. Training Period: 
             1. Begin Date = 2001-01-01 
             2. End Date   = 2005-12-31  
         2. Validation Period: 
             1. Begin Date = 2006-01-01 
             2. End Date   = 2007-06-30   
     4. Test Period: 
         1. Begin Date = 2008-01-01 
         2. End Date   = 2008-12-31         
Portfolio Trade Assets
In [86]:
portfolio_trade_assets   = [ "^DJI", "^IXIC", "^GSPC" ]
Market Data Manager
In [87]:
dirPathMarketData = '/Users/gustavozambrana/Google Drive/Python/Projects/Trade_Engine/Data/US_Market_Indixes'

supportedTradeAssets   = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str           = "2000-01-01"
end_date_str           = None

ts_marketdat_mng = TradeStrategyMarketDataMng(\
        marketDataProviderName = "yahoofinance",
        supportedTradeAssets   = supportedTradeAssets,
        stock_price_col_name   = "Adj Close",
        fileNameMarketData     = "US_Indixes_And_ETFs_MrkData",
        dirPathMarketData      = dirPathMarketData,
        beg_date_str           = beg_date_str,
        end_date_str           = end_date_str,
        interval               = "1d"  ) 
2021-10-28 15:44:35,256 [INFO] root: Found previous Market data previously loaded to specified file and dir.
Simulation Broker
In [89]:
brokerTradingObj = SimBrokerTrading()
Trade Strategies, Trade Investment Manager, and Trade Asset Register Items
In [92]:
tsConfDat = TradeStrategyConfigData()

# Set Config

tsConfDat.tsSetConfig(\
    ts_set_conf_dict = 
           { 'set_actions_conf' : 
                      { "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
                        "exit"  : { 'votingPolicy' : 1, 
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1 } 
                      }
           } )
           
# TS #1

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_lstm_1",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 3,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'         : 20 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 1, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },
                             },
                    }  )

# TS #2

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_lstm_2",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps' : 100, 'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 15,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'         : 20 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 1, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },
                             },
                    }  )

# TS #3

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_lstm_3",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'         : 20 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 1, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },
                             },
                    }  )

# TS #4

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_lstm_4",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'         : 20 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 1, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 2 } },
                             },
                    }  )

# TS #5

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_lstm_5",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps' : 40, 'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 3,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'         : 20 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 1, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },
                             },
                    }  )

# TS #6

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_lstm_6",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps' : 30, 'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 3,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'         : 20 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 1, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },
                             },
                    }  )

# TS #7

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_lstm_7",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps' : 60, 'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'         : 20 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 1, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },
                             },
                    }  )
In [ ]:
taRegisterItems = [ ]
tsActionGen = TradeStrategyActionGenerator()

for trade_asset in portfolio_trade_assets :
    
    num_ts = len(tsConfDat.name_list) + 1  # adding the composite  trade strategy
    
    for i in range( num_ts ) :

        if i <= num_ts - 2:
            # *** Trade Strategy 

            actionDatItem  = tsConfDat.getTSConfigDataForItem(item_num = i )
            ts_unique_name = actionDatItem.name_list[0]
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = actionDatItem,
                                                     pipelineMng       = None )
        else :
            # Composite Trade Strategy 
            
            ts_unique_name = "all"            
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = tsConfDat,
                                                     pipelineMng       = None )

        ts_model = TradeStrategyBaseModelPersist(\
                        trade_asset               = trade_asset,
                        ts_marketdat_mng          = ts_marketdat_mng,
                        ts_enter                  = trade_enter_set,
                        ts_exit                   = trade_exit_set,                       
                        model_type                = ts_unique_name,
                        model_version             = "1.0",
                        market_data_period        = MarketDataPeriod.Day,
                    ) 

        # *** Trade Strategy Investment Manager 

        taInvMng = TradingAssetInvMngBase(\
                                        trade_asset                = trade_asset,
                                        minPeriodsBetweenTrades    = 1,
                                        initInvestment             = 1000000.0, 
                                        capPercentToInvestPerTrade = 100.0,
                                        minInvestPercent           = 5.0,
                                        min_account_balance        = 1000.0 )

        # *** Trade Register Item
        # *** This object has all configuration defined to execute a given trade strategy,
        # *** It can be executed individually in backtest or as part of a portfolio

        ta_registered_item = TradingAssetRegisterItem(\
                trade_name                    = "{0}_{1}".format(ts_unique_name, trade_asset), 
                ts_model                      = ts_model,
                tradingExecutionType          = TradingAssetExecutionType.Simulation,
                tradingBrokerObj              = brokerTradingObj,
                tradingAssetInvMngObj         = taInvMng )  

        taRegisterItems.append(ta_registered_item)
In [94]:
print("Number of configured Trade Asset Register Items: ", len(taRegisterItems) )
Number of configured Trade Asset Register Items:  24
Portfolio Investment Manager
In [95]:
# *** Porttfolio Investment Manager across all individual trade strategies investment managers
# *** Role: 
# ***    1) Managed investment funds across n number of trade strategies
# ***    2) Rebalance portfolio periodically or never
# ***    3) Portfolio Policy Weights 
# ***          equal weights (default)
# ***          MinimumVariance
# ***          User defined 
# ***    4) Track Portfolio level returns and metrics
# ***          Individual Trade Strategies return and metrics tracked through their 
# ***          investment managers
# ***          Portfolio funds are split across each trade strategy investment manager based on the
# ***          portfolio weights

portfInvMng = PortfolioInvMng(\
                  name                       = "Portfolio Inv. Manager for US-Indexes - Multiple-LSTM  TS",
                  initInvestment             = 2000000.0 * ( len(taRegisterItems) + 3),  # 200K/trade-strag
                  portfRebalanceFreq         = PortfolioRebalanceFrequency.Never,
                  portfRebalancePeriods      = 1,
                  minInvestPercent           = 5.0,
                  min_account_balance        = 1000.0,     
                  minPeriodsBetweenTrades    = 1,
                  capPercentToInvestPerTrade = 100.0 )
Trade Register Items Portfolio
In [96]:
# *** Set of Trade Register Items
#
# Configuration Summary:
#    - Each set has 1 to n trade register items as previously described 
#    - Optionally add long only trade strategies for all unique trade assets in the
#      portfolio 
#           - (Dow, Nasdaq, and S&P 500 for this portfolio) in this example
#           - Might be useful for bench marking trade strategies
#    - Each set has one Investment Portfolio Manager
#       - portfolio funds allocated per portfolio policy rules and re-balanced (if defined), 
#         across all trade strategies


portf_registered_obj = PortfolioRegisterItem(\
                        name                 = "Portfolio D, US-Indexes with Multiple-LSTM and Long strategies",
                        taRegisterItems      = taRegisterItems,
                        portfolioInvMngObj   = portfInvMng,
                        tradingExecutionType = TradingAssetExecutionType.Simulation,
                        add_long_only_ts     = True )
2021-10-28 15:48:18,655 [INFO] root: *** Adding long only trade strategies for : {'^GSPC', '^IXIC', '^DJI'}
Persist to DB (optional)
In [97]:
session.add( portf_registered_obj )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")
 done
Re-Store from DB (optional)
In [98]:
session.expunge_all()
del portf_registered_obj

for tsObj in session.query(PortfolioRegisterItem):  
    print(tsObj.name)
    if  tsObj.name  == "Portfolio D, US-Indexes with Multiple-LSTM and Long strategies" :
        break

portf_registered_obj = tsObj
print(portf_registered_obj.id, portf_registered_obj.name)
2021-10-28 15:48:30,980 [INFO] root: PortfolioRegisterItem init called. 
2021-10-28 15:48:30,981 [INFO] root: PortfolioRegisterItem init called. 
2021-10-28 15:48:30,982 [INFO] root: PortfolioRegisterItem init called. 
2021-10-28 15:48:30,982 [INFO] root: PortfolioRegisterItem init called. 
2021-10-28 15:48:30,983 [INFO] root: PortfolioRegisterItem init called. 
Portfolio of US-Indexes using SMA and Long strategies
Portfolio of US-Indexes using LSTM and Long strategies
Portfolio of US-Indexes with Multiple-SMA and Long strategies
Portfolio of US-Indexes with Multiple-SMA and Long strategies
Portfolio of US-Indexes with Multiple-LSTM and Long strategies
5 Portfolio of US-Indexes with Multiple-LSTM and Long strategies
Training, Validation and Test Periods for Backtest

In Order to backtest a trade strategy or portfolio that has AI models, the following data is required:

  1. Training Date Range

    1. Date range that will be used to train the AI models in the backtest
  2. Validation Date Range

    1. Date range that twill be used to validate the AI models, should not overlapped with the training date range
  3. Test Period Date Range

    1. This is the out-sample date range, which corresponds to the date range of the backtest

Date Ranges are defined with a DatasetDef object, and have the following parameters:

  1. strBegDateAIModels : Date to begin training or validation of an AI model
  2. strBegDate : Date to begin the backtest
  3. strEndDate : Date to end training, validation and Backtest

Note:

  1. The param strBegDateAIModels can be defined as the same date as strBegDate, that is the default, if not defined.
  2. The critical aspect of using this parameter is in the backtest. Some AI Models, such as time series, others using moving averages over many periods, create params with no predicting data for those initial dates. Thus, in order to ensure the backtest starts on the actual date specified, the strBegDateAIModels should be defined as an earlier date, and it should not overlapped with the validation period end-date to avoid any chance of bias by picking at the validation data.
In [99]:
training_period = DatasetDef(datasetType = DatasetType.Training,
                             strBegDateAIModels = "2000-07-01",
                             strBegDate         = "2001-01-01",
                             strEndDate         = "2005-12-31" )

validation_period = DatasetDef(datasetType = DatasetType.Validation,
                               strBegDateAIModels = "2005-07-01",
                               strBegDate         = "2006-01-01",
                               strEndDate         = "2007-06-30" )

testing_period = DatasetDef(datasetType = DatasetType.Testing,
                               strBegDateAIModels = "2007-07-01",
                               strBegDate         = "2008-01-01",
                               strEndDate         = "2008-12-31" )

fit_datasets = FitDatasetsDef( trainingDataset    = training_period,
                               validationDataset  = validation_period )
Execute Backtest
In [100]:
tsExecuteEngine = BacktestExecution( \
                    name = "Backtest for Portfolio of Multiple-LSTM based Trade Strategies",
                    timePeriod  = testing_period,
                    fitDatasets = fit_datasets,
                    trade_asset_registered_item = portf_registered_obj )
In [ ]:
tsExecuteEngine.evaluate()
Backtest Metrics
Execution & Investment Metrics
In [102]:
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
        'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']]
Out[102]:
TA_Reg_Name Is_Portfolio Num_Trades_Completed Init_Capital Final_Capital Cum_Return Backtest_Status
0 Portfolio of US-Indexes with Multiple-LSTM and... Yes 880 54000000.0 8.098601e+07 0.499741 Completed
1 ts_lstm_1_^DJI No 62 2000000.0 4.567614e+06 1.283807 Completed
2 ts_lstm_2_^DJI No 44 2000000.0 3.582771e+06 0.791385 Completed
3 ts_lstm_3_^DJI No 45 2000000.0 3.635315e+06 0.817657 Completed
4 ts_lstm_4_^DJI No 25 2000000.0 2.175172e+06 0.087586 Completed
5 ts_lstm_5_^DJI No 68 2000000.0 4.905520e+06 1.452760 Completed
6 ts_lstm_6_^DJI No 60 2000000.0 4.447922e+06 1.223961 Completed
7 ts_lstm_7_^DJI No 43 2000000.0 3.115092e+06 0.557546 Completed
8 all_^DJI No 50 2000000.0 3.472202e+06 0.736101 Completed
9 ts_lstm_1_^IXIC No 56 2000000.0 5.493883e+06 1.746941 Completed
10 ts_lstm_2_^IXIC No 49 2000000.0 2.720286e+06 0.360143 Completed
11 ts_lstm_3_^IXIC No 50 2000000.0 4.760641e+06 1.380321 Completed
12 ts_lstm_4_^IXIC No 23 2000000.0 1.733701e+06 -0.133149 Completed
13 ts_lstm_5_^IXIC No 54 2000000.0 4.355464e+06 1.177732 Completed
14 ts_lstm_6_^IXIC No 54 2000000.0 4.423564e+06 1.211782 Completed
15 ts_lstm_7_^IXIC No 55 2000000.0 4.932952e+06 1.466476 Completed
16 all_^IXIC No 54 2000000.0 4.976641e+06 1.488320 Completed
17 ts_lstm_1_^GSPC No 21 2000000.0 2.176975e+06 0.088488 Completed
18 ts_lstm_2_^GSPC No 6 2000000.0 1.537192e+06 -0.231404 Completed
19 ts_lstm_3_^GSPC No 5 2000000.0 1.466085e+06 -0.266957 Completed
20 ts_lstm_4_^GSPC No 5 2000000.0 1.393045e+06 -0.303478 Completed
21 ts_lstm_5_^GSPC No 21 2000000.0 2.184461e+06 0.092231 Completed
22 ts_lstm_6_^GSPC No 17 2000000.0 2.029246e+06 0.014623 Completed
23 ts_lstm_7_^GSPC No 3 2000000.0 1.466923e+06 -0.266538 Completed
24 all_^GSPC No 7 2000000.0 1.628941e+06 -0.185530 Completed
25 Long-Only Trade Strategy for ^GSPC No 1 2000000.0 1.248316e+06 -0.375842 Completed
26 Long-Only Trade Strategy for ^IXIC No 1 2000000.0 1.209029e+06 -0.395486 Completed
27 Long-Only Trade Strategy for ^DJI No 1 2000000.0 1.347062e+06 -0.326469 Completed
Performance Metrics
In [103]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ]
Out[103]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
0 Portfolio of US-Indexes with Multiple-LSTM and... Yes 2008-01-03 2008-12-31 1.0 0.5 0.5 1.45 -0.22 0.11 -0.07
1 ts_lstm_1_^DJI No ts_lstm_1 ^DJI 2008-01-03 2008-12-31 1.0 1.28 1.29 2.37 -0.24 0.11 -0.07
2 ts_lstm_2_^DJI No ts_lstm_2 ^DJI 2008-01-03 2008-12-31 1.0 0.79 0.8 1.72 -0.24 0.11 -0.08
3 ts_lstm_3_^DJI No ts_lstm_3 ^DJI 2008-01-03 2008-12-31 1.0 0.82 0.82 1.76 -0.22 0.11 -0.08
4 ts_lstm_4_^DJI No ts_lstm_4 ^DJI 2008-01-03 2008-12-31 1.0 0.09 0.09 0.41 -0.28 0.11 -0.08
5 ts_lstm_5_^DJI No ts_lstm_5 ^DJI 2008-01-03 2008-12-31 1.0 1.45 1.46 2.57 -0.24 0.11 -0.07
6 ts_lstm_6_^DJI No ts_lstm_6 ^DJI 2008-01-03 2008-12-31 1.0 1.22 1.23 2.3 -0.24 0.11 -0.07
7 ts_lstm_7_^DJI No ts_lstm_7 ^DJI 2008-01-03 2008-12-31 1.0 0.56 0.56 1.35 -0.26 0.11 -0.08
8 all_^DJI No all ^DJI 2008-01-03 2008-12-31 1.0 0.74 0.74 1.64 -0.24 0.11 -0.08
9 ts_lstm_1_^IXIC No ts_lstm_1 ^IXIC 2008-01-03 2008-12-31 1.0 1.75 1.76 2.67 -0.23 0.12 -0.07
10 ts_lstm_2_^IXIC No ts_lstm_2 ^IXIC 2008-01-03 2008-12-31 1.0 0.36 0.36 0.95 -0.33 0.12 -0.09
11 ts_lstm_3_^IXIC No ts_lstm_3 ^IXIC 2008-01-03 2008-12-31 1.0 1.38 1.39 2.31 -0.21 0.12 -0.07
12 ts_lstm_4_^IXIC No ts_lstm_4 ^IXIC 2008-01-03 2008-12-31 1.0 -0.13 -0.13 -0.14 -0.26 0.12 -0.07
13 ts_lstm_5_^IXIC No ts_lstm_5 ^IXIC 2008-01-03 2008-12-31 1.0 1.18 1.19 2.09 -0.25 0.12 -0.07
14 ts_lstm_6_^IXIC No ts_lstm_6 ^IXIC 2008-01-03 2008-12-31 1.0 1.21 1.22 2.13 -0.25 0.12 -0.07
15 ts_lstm_7_^IXIC No ts_lstm_7 ^IXIC 2008-01-03 2008-12-31 1.0 1.47 1.48 2.4 -0.23 0.12 -0.07
16 all_^IXIC No all ^IXIC 2008-01-03 2008-12-31 1.0 1.49 1.5 2.43 -0.23 0.12 -0.07
17 ts_lstm_1_^GSPC No ts_lstm_1 ^GSPC 2008-01-03 2008-12-31 1.0 0.09 0.09 0.41 -0.26 0.12 -0.09
18 ts_lstm_2_^GSPC No ts_lstm_2 ^GSPC 2008-01-03 2008-12-31 1.0 -0.23 -0.23 -0.44 -0.41 0.12 -0.09
19 ts_lstm_3_^GSPC No ts_lstm_3 ^GSPC 2008-01-03 2008-12-31 1.0 -0.27 -0.27 -0.55 -0.48 0.12 -0.09
20 ts_lstm_4_^GSPC No ts_lstm_4 ^GSPC 2008-01-03 2008-12-31 1.0 -0.3 -0.3 -0.68 -0.48 0.12 -0.09
21 ts_lstm_5_^GSPC No ts_lstm_5 ^GSPC 2008-01-03 2008-12-31 1.0 0.09 0.09 0.42 -0.26 0.12 -0.09
22 ts_lstm_6_^GSPC No ts_lstm_6 ^GSPC 2008-01-03 2008-12-31 1.0 0.01 0.01 0.24 -0.32 0.12 -0.09
23 ts_lstm_7_^GSPC No ts_lstm_7 ^GSPC 2008-01-03 2008-12-31 1.0 -0.27 -0.27 -0.55 -0.48 0.12 -0.09
24 all_^GSPC No all ^GSPC 2008-01-03 2008-12-31 1.0 -0.19 -0.19 -0.3 -0.42 0.12 -0.09
25 Long-Only Trade Strategy for ^GSPC No long ^GSPC 2008-01-03 2008-12-31 1.0 -0.38 -0.38 -0.94 -0.48 0.12 -0.09
26 Long-Only Trade Strategy for ^IXIC No long ^IXIC 2008-01-03 2008-12-31 1.0 -0.4 -0.4 -1.02 -0.49 0.12 -0.09
27 Long-Only Trade Strategy for ^DJI No long ^DJI 2008-01-03 2008-12-31 1.0 -0.33 -0.33 -0.86 -0.42 0.11 -0.08
In [104]:
tsExecuteEngine.getSummaryMetrics().T.head(60)
Out[104]:
0 1 2 3 4 5 6 7 8 9 ... 18 19 20 21 22 23 24 25 26 27
ta_reg_item_name Portfolio of US-Indexes with Multiple-LSTM and... ts_lstm_1_^DJI ts_lstm_2_^DJI ts_lstm_3_^DJI ts_lstm_4_^DJI ts_lstm_5_^DJI ts_lstm_6_^DJI ts_lstm_7_^DJI all_^DJI ts_lstm_1_^IXIC ... ts_lstm_2_^GSPC ts_lstm_3_^GSPC ts_lstm_4_^GSPC ts_lstm_5_^GSPC ts_lstm_6_^GSPC ts_lstm_7_^GSPC all_^GSPC Long-Only Trade Strategy for ^GSPC Long-Only Trade Strategy for ^IXIC Long-Only Trade Strategy for ^DJI
ta_reg_item_id 5 67 68 69 70 71 72 73 74 75 ... 84 85 86 87 88 89 90 91 92 93
is_portfolio Yes No No No No No No No No No ... No No No No No No No No No No
model_type ts_lstm_1 ts_lstm_2 ts_lstm_3 ts_lstm_4 ts_lstm_5 ts_lstm_6 ts_lstm_7 all ts_lstm_1 ... ts_lstm_2 ts_lstm_3 ts_lstm_4 ts_lstm_5 ts_lstm_6 ts_lstm_7 all long long long
trade_asset ^DJI ^DJI ^DJI ^DJI ^DJI ^DJI ^DJI ^DJI ^IXIC ... ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^IXIC ^DJI
test_period_len_days 365 365 365 365 365 365 365 365 365 365 ... 365 365 365 365 365 365 365 365 365 365
tr_period_len_days 1825 1825 1825 1825 1825 1825 1825 1825 1825 1825 ... 1825 1825 1825 1825 1825 1825 1825 1825 1825 1825
val_period_len_days 545 545 545 545 545 545 545 545 545 545 ... 545 545 545 545 545 545 545 545 545 545
index Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy ... Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy
Start Period 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 ... 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03
End Period 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31 ... 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31
Risk-Free Rate 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
Time in Market 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 ... 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
Cumulative Return 0.5 1.28 0.79 0.82 0.09 1.45 1.22 0.56 0.74 1.75 ... -0.23 -0.27 -0.3 0.09 0.01 -0.27 -0.19 -0.38 -0.4 -0.33
CAGR% 0.5 1.29 0.8 0.82 0.09 1.46 1.23 0.56 0.74 1.76 ... -0.23 -0.27 -0.3 0.09 0.01 -0.27 -0.19 -0.38 -0.4 -0.33
Sharpe 1.45 2.37 1.72 1.76 0.41 2.57 2.3 1.35 1.64 2.67 ... -0.44 -0.55 -0.68 0.42 0.24 -0.55 -0.3 -0.94 -1.02 -0.86
Sortino 2.5 4.08 2.8 2.98 0.64 4.42 3.95 2.22 2.65 4.81 ... -0.62 -0.79 -0.96 0.65 0.37 -0.79 -0.43 -1.29 -1.4 -1.2
Sortino/√2 1.76 2.88 1.98 2.11 0.45 3.12 2.79 1.57 1.87 3.4 ... -0.44 -0.56 -0.68 0.46 0.26 -0.56 -0.3 -0.91 -0.99 -0.85
Max Drawdown -0.22 -0.24 -0.24 -0.22 -0.28 -0.24 -0.24 -0.26 -0.24 -0.23 ... -0.41 -0.48 -0.48 -0.26 -0.32 -0.48 -0.42 -0.48 -0.49 -0.42
Longest DD Days 65 51 78 63 92 48 48 154 71 54 ... 362 362 362 126 225 362 362 362 362 240
Volatility (ann.) 0.31 0.38 0.38 0.38 0.38 0.38 0.38 0.38 0.38 0.41 ... 0.41 0.41 0.41 0.41 0.41 0.41 0.41 0.41 0.41 0.38
Calmar 2.3 5.37 3.31 3.73 0.32 6.07 5.12 2.15 3.08 7.58 ... -0.57 -0.56 -0.64 0.36 0.05 -0.56 -0.44 -0.79 -0.8 -0.78
Skew 1.36 0.7 0.54 0.75 0.82 0.68 0.71 0.71 0.53 0.8 ... 0.21 0.45 0.44 0.75 0.73 0.45 0.47 0.18 0.21 0.43
Kurtosis 8.96 3.88 4.0 3.92 4.19 3.91 3.88 3.98 3.98 2.75 ... 3.96 4.01 4.04 3.95 3.98 4.01 3.97 3.99 3.22 4.22
Expected Daily % 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... -0.0 -0.0 -0.0 0.0 0.0 -0.0 -0.0 -0.0 -0.0 -0.0
Expected Monthly % 0.03 0.07 0.05 0.05 0.01 0.08 0.07 0.04 0.05 0.09 ... -0.02 -0.03 -0.03 0.01 0.0 -0.03 -0.02 -0.04 -0.04 -0.03
Expected Yearly % 0.5 1.28 0.79 0.82 0.09 1.45 1.22 0.56 0.74 1.75 ... -0.23 -0.27 -0.3 0.09 0.01 -0.27 -0.19 -0.38 -0.4 -0.33
Kelly Criterion 0.16 0.2 0.15 0.15 0.04 0.23 0.2 0.12 0.14 0.22 ... -0.04 -0.06 -0.07 0.04 0.02 -0.05 -0.03 -0.1 -0.09 -0.08
Risk of Ruin 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
Daily Value-at-Risk -0.03 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 ... -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04
Expected Shortfall (cVaR) -0.03 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 ... -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04
Gain/Pain Ratio 0.4 0.56 0.38 0.39 0.08 0.61 0.54 0.29 0.36 0.62 ... -0.08 -0.1 -0.12 0.08 0.05 -0.1 -0.05 -0.16 -0.17 -0.15
Gain/Pain (1M) 3.33 46.57 2.83 4.82 0.59 inf 45.25 1.78 3.45 6.99 ... -0.43 -0.46 -0.58 0.72 0.37 -0.45 -0.29 -0.81 -0.69 -0.82
Payoff Ratio 1.05 1.17 1.16 1.22 1.04 1.12 1.15 1.17 1.12 1.22 ... 0.86 0.88 0.86 0.99 0.97 0.89 0.91 0.83 0.96 0.92
Profit Factor 1.4 1.56 1.38 1.39 1.08 1.61 1.54 1.29 1.36 1.62 ... 0.92 0.9 0.88 1.08 1.05 0.9 0.95 0.84 0.83 0.85
Common Sense Ratio 2.01 2.07 1.6 1.81 1.32 2.14 2.04 1.54 1.6 2.3 ... 0.97 0.89 0.87 1.25 1.13 0.89 1.0 0.76 0.77 0.74
CPC Index 0.84 1.04 0.87 0.9 0.57 1.07 1.01 0.79 0.83 1.13 ... 0.41 0.4 0.38 0.56 0.53 0.41 0.44 0.35 0.37 0.38
Tail Ratio 1.44 1.33 1.16 1.31 1.23 1.33 1.33 1.19 1.18 1.42 ... 1.06 0.99 0.99 1.16 1.08 0.99 1.06 0.91 0.92 0.86
Outlier Win Ratio 6.45 4.63 4.32 4.35 4.54 4.73 4.66 4.42 4.38 4.7 ... 4.18 4.92 4.94 5.44 5.49 4.88 4.84 4.26 3.61 4.23
Outlier Loss Ratio 5.24 3.77 4.19 3.65 3.55 3.67 3.74 3.74 4.11 3.26 ... 4.36 3.85 3.81 3.64 3.61 3.88 3.91 4.3 4.04 4.23
MTD 0.27 0.38 0.29 0.3 0.04 0.38 0.36 0.3 0.38 0.26 ... 0.01 0.21 0.12 0.22 0.22 0.21 0.21 0.01 0.03 -0.01
3M 0.17 0.5 0.14 0.19 -0.14 0.5 0.48 0.07 0.23 0.23 ... -0.0 -0.04 -0.09 0.08 0.08 -0.04 0.07 -0.18 -0.2 -0.15
6M 0.39 0.91 0.62 0.81 0.08 0.89 0.85 0.62 0.6 0.97 ... -0.14 -0.17 -0.22 0.13 0.01 -0.17 -0.08 -0.29 -0.31 -0.23
YTD 0.5 1.28 0.79 0.82 0.09 1.45 1.22 0.56 0.74 1.75 ... -0.23 -0.27 -0.3 0.09 0.01 -0.27 -0.19 -0.38 -0.4 -0.33
1Y 0.5 1.28 0.79 0.82 0.09 1.45 1.22 0.56 0.74 1.75 ... -0.23 -0.27 -0.3 0.09 0.01 -0.27 -0.19 -0.38 -0.4 -0.33
3Y (ann.) 0.5 1.29 0.8 0.82 0.09 1.46 1.23 0.56 0.74 1.76 ... -0.23 -0.27 -0.3 0.09 0.01 -0.27 -0.19 -0.38 -0.4 -0.33
5Y (ann.) 0.5 1.29 0.8 0.82 0.09 1.46 1.23 0.56 0.74 1.76 ... -0.23 -0.27 -0.3 0.09 0.01 -0.27 -0.19 -0.38 -0.4 -0.33
10Y (ann.) 0.5 1.29 0.8 0.82 0.09 1.46 1.23 0.56 0.74 1.76 ... -0.23 -0.27 -0.3 0.09 0.01 -0.27 -0.19 -0.38 -0.4 -0.33
All-time (ann.) 0.5 1.29 0.8 0.82 0.09 1.46 1.23 0.56 0.74 1.76 ... -0.23 -0.27 -0.3 0.09 0.01 -0.27 -0.19 -0.38 -0.4 -0.33
Best Day 0.11 0.11 0.11 0.11 0.11 0.11 0.11 0.11 0.11 0.12 ... 0.12 0.12 0.12 0.12 0.12 0.12 0.12 0.12 0.12 0.11
Worst Day -0.07 -0.07 -0.08 -0.08 -0.08 -0.07 -0.07 -0.08 -0.08 -0.07 ... -0.09 -0.09 -0.09 -0.09 -0.09 -0.09 -0.09 -0.09 -0.09 -0.08
Best Month 0.27 0.38 0.29 0.3 0.1 0.38 0.36 0.3 0.38 0.44 ... 0.13 0.21 0.12 0.22 0.22 0.21 0.21 0.05 0.06 0.05
Worst Month -0.08 -0.02 -0.15 -0.1 -0.14 -0.01 -0.02 -0.12 -0.15 -0.14 ... -0.17 -0.17 -0.17 -0.14 -0.14 -0.17 -0.17 -0.17 -0.18 -0.14
Best Year 0.5 1.28 0.79 0.82 0.09 1.45 1.22 0.56 0.74 1.75 ... -0.23 -0.27 -0.3 0.09 0.01 -0.27 -0.19 -0.38 -0.4 -0.33
Worst Year 0.5 1.28 0.79 0.82 0.09 1.45 1.22 0.56 0.74 1.75 ... -0.23 -0.27 -0.3 0.09 0.01 -0.27 -0.19 -0.38 -0.4 -0.33
Avg. Drawdown -0.02 -0.04 -0.04 -0.04 -0.05 -0.04 -0.03 -0.05 -0.04 -0.04 ... -0.41 -0.48 -0.48 -0.06 -0.05 -0.48 -0.42 -0.48 -0.49 -0.26
Avg. Drawdown Days 12 8 15 18 24 8 8 24 15 8 ... 362 362 362 30 27 362 362 362 362 180
Recovery Factor 2.29 5.32 3.28 3.7 0.32 6.02 5.08 2.13 3.06 7.51 ... -0.57 -0.56 -0.63 0.36 0.05 -0.56 -0.44 -0.78 -0.8 -0.78
Ulcer Index 4.92 1.79 1.81 1.8 1.82 1.79 1.79 1.81 1.8 1.45 ... inf inf inf inf inf inf inf inf 1.56 1.86
Avg. Up Month 0.08 0.09 0.12 0.11 0.06 0.09 0.09 0.11 0.11 0.15 ... 0.04 0.07 0.05 0.06 0.06 0.07 0.06 0.02 0.03 0.02

60 rows × 28 columns

Persist Backtest to DB (optional )
In [ ]:
session.add( tsExecuteEngine )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst)
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")

Portfolio E

  1. Portfolio E: Long and Eleven Distinct Technical Analysis Based Trade Strategies for US Indixes

    Description:

     1. Portfolio with 39 trading strategies
     2. $200,000/strategy, Total Budget = $7.8M
     3. No-Rebalance during the backtest 
     4. 100% capital invested
     5. Portfolio investment using equal weights for each trade strategy
    
    

    Trade Strategies:

     1. Three trade strategies: Nasdaq, S&P 500, and DOW Jones with buy-and-hold
    
     2. 33 trade strategies: Nasdaq, S&P 500, and DOW Jones using following TA Indicators & Configurations:
    
        See: https://technical-analysis-library-in-python.readthedocs.io/en/latest/index.html for 
        explanation on the technical indicator specific parameters
    
             TS-No    TA-Indicator                 Parameters
    
               1           sma           fast_mav                      10 
                                         slow_mav                      50 
                                         enter_if_last_nmatch           2 
                                         enter_if_cross_over_sig      Yes
                                         exit_if_last_nmatch            1
    
               2            bb           window                        20
                                         window_dev                     1
                                         enter_if_last_nmatch           2 
                                         enter_if_cross_over_sig      Yes
                                         exit_if_last_nmatch            1     
    
               3          macd           window_slow                   26
                                         window_fast                   12
                                         window_sign                    9
                                         enter_if_last_nmatch           2
                                         enter_if_cross_over_sig      Yes
                                         exit_if_last_nmatch            1 
    
               4           rsi           enter_long if rsi  <=         30
                                         exit_long  if rsi  >          30
                                         enter_short if rsi >=         70
                                         exit_short if rsi  <=         60
                                         enter_if_last_nmatch           2
                                         enter_if_cross_over_sig      Yes
                                         exit_if_last_nmatch            1 
    
               5          srsi           window                        14
                                         smooth1                        3
                                         smooth2                        3
                                         enter_long if stochrsi_d >=  0.5
                                         exit_long if stochrsi_d  <   0.5
                                         enter_if_last_nmatch           2
                                         enter_if_cross_over_sig      Yes
                                         exit_if_last_nmatch            1 
    
               6           adx           window                        14
                                         enter_if_last_nmatch           2
                                         enter_if_cross_over_sig      Yes
                                         exit_if_last_nmatch            1 
    
               7         mkama           kama_fast_window              10
                                         kama_fast_pow1                 2
                                         kama_fast_pow1                30
                                         kama_slow_window              10
                                         kama_slow_pow1                 5
                                         kama_slow_pow1                30
                                         enter_if_last_nmatch           2
                                         enter_if_cross_over_sig      Yes
                                         exit_if_last_nmatch            1 
    
               8           tsi           window_slow                   25
                                         window_fast                    5
                                         enter_if_last_nmatch           2
                                         enter_if_cross_over_sig      Yes
                                         exit_if_last_nmatch            1 
    
               9      forceidx           window                        13
                                         enter_if_last_nmatch           2
                                         enter_if_cross_over_sig      Yes
                                         exit_if_last_nmatch            1 
    
              10           mfi           window                        14
                                         no mfi points for slope        5
                                         enter_if_last_nmatch           2
                                         enter_if_cross_over_sig      Yes
                                         exit_if_last_nmatch            1 
    
              11           sma           fast_mav                      15 
                                         slow_mav                      60 
                                         enter_if_last_nmatch           2 
                                         enter_if_cross_over_sig      Yes
                                         exit_if_last_nmatch            1
    
     3. Three trade strategies: Nasdaq, S&P 500, and DOW Jones using the following configuration: 
    
         - A Composite Trade Strategy based on all the technical-analysis indicators configured 
           above
    
         - The Set Entry cofiguration rules are: 
           a. Majority Voting (default)
           b. Enter a trade if the last n voting decisions are the same, set to 1 (default )
           c. Enter a trade if there is cross-over signaled after applying rules a) and b), 
              set to False
    
         - The Set Exit configuration rules are: 
           a. Majority Voting (Default)
           b. Exit a trade if the last n exit decisions are the same, set to 1 (default )
    
    

    Backtest:

     1. Type: regular
     2. Test Period: 
         1. Begin Date = 2006-01-01 
         2. End Date   = 2010-12-31 
Portfolio Trade Assets
In [105]:
portfolio_trade_assets   = [ "^DJI", "^IXIC", "^GSPC" ]
Market Data Manager
In [106]:
dirPathMarketData = '/Users/gustavozambrana/Google Drive/Python/Projects/Trade_Engine/Data/US_Market_Indixes'

supportedTradeAssets   = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str           = "2000-01-01"
end_date_str           = None

ts_marketdat_mng = TradeStrategyMarketDataMng(\
        marketDataProviderName = "yahoofinance",
        supportedTradeAssets   = supportedTradeAssets,
        stock_price_col_name   = "Adj Close",
        fileNameMarketData     = "US_Indixes_And_ETFs_MrkData",
        dirPathMarketData      = dirPathMarketData,
        beg_date_str           = beg_date_str,
        end_date_str           = end_date_str,
        interval               = "1d"  ) 
2021-10-28 16:40:59,791 [INFO] root: Found previous Market data previously loaded to specified file and dir.
Simulation Broker
In [107]:
brokerTradingObj = SimBrokerTrading()
Trade Strategies, Trade Investment Manager, and Trade Asset Register Items
In [108]:
tsConfDat = TradeStrategyConfigData()

# Set Config

tsConfDat.tsSetConfig(\
    ts_set_conf_dict = 
           { 'set_actions_conf' : 
                      { "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
                        "exit"  : { 'votingPolicy' : 1, 
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1 } 
                      }
           } )          
# TS #1

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_1",    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 10, 'win_slow' : 50 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 },
                                },
                            }  } )
# TS #2

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_2",    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 15, 'win_slow' : 60 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 },
                                },
                            }  } )
# TS #3

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_bb",    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "bb",
                                  'type'     : "ta",
                                  'obj_args' : { 'window' : 13, 'window_dev' : 1 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 },
                                },
                            }  } )
# TS #4

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_macd",    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "macd",
                                  'type'     : "ta",
                                  'obj_args' : { 'window_slow' : 26, 'window_fast' : 12, 'window_sign' : 9,
                                                 'enter_long_macd_diff'  : 0.5 , 'exi_long_macd_diff' : 0.5,
                                                 'enter_short_macd_diff' : -0.5, 'exi_short_macd_diff' : -0.5  },
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 },
                                },
                            }  } )
# TS #5

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_rsi",    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "rsi",
                                  'type'     : "ta",
                                  'obj_args' : { 'rsi_enter_long'  : 30.0,  'rsi_exit_long'  : 30.0, 
                                                 'rsi_enter_short' : 70.0,  'rsi_exit_short' : 70.0 },
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 },
                                },
                            }  } )
# TS #6

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_srsi",    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "srsi",
                                  'type'     : "ta",
                                  'obj_args' : { 'window' : 14,  'smooth1' : 3, 'smooth2'  : 3,
                                                 'srsi_enter_long'  : 0.8,  'srsi_exit_long'  : 0.8,
                                                 'srsi_enter_short' : 0.2,  'srsi_exit_short' : 0.2 },
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 },
                                },
                            }  } )
# TS #7

tsConfDat.addTSConf(\
   ts_conf_dict = { 
      'ts_unique_tag' : "ts_adx",    
      'actions_conf'  : { "entry_exit" :  
                            { 'model'    : "adx",
                              'type'     : "ta",
                              'obj_args' : { 'window' : 14, 'adx_enter_long_ge' : 14, 'adx_exit_long_lt'  : 14,
                                             'adx_enter_short_ge' : 14, 'adx_exit_short_lt' : 14 },
                              'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                              'exit_policy_args'   : { 'lastn_match' : 1 },
                            },
                        }  } )
# TS #8

tsConfDat.addTSConf(\
   ts_conf_dict = { 
      'ts_unique_tag' : "ts_kama",    
      'actions_conf'  : { "entry_exit" :  
                            { 'model'    : "kama",
                              'type'     : "ta",
                              'obj_args' : { 'window_fast' : 10, 'pow1_fast' : 2, 'pow2_fast'  : 30,
                                             'window_slow' : 10, 'pow1_slow' : 5, 'pow2_slow'  : 30 },
                              'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                              'exit_policy_args'   : { 'lastn_match' : 1 },
                            },
                        }  } )
# TS #9

tsConfDat.addTSConf(\
   ts_conf_dict = { 
      'ts_unique_tag' : "ts_tsi",    
      'actions_conf'  : { "entry_exit" :  
                            { 'model'    : "tsi",
                              'type'     : "ta",
                              'obj_args' : { 'window_slow' : 25, 'window_fast' : 5 },
                              'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                              'exit_policy_args'   : { 'lastn_match' : 1 },
                            },
                        }  } )

# TS #10

tsConfDat.addTSConf(\
   ts_conf_dict = { 
      'ts_unique_tag' : "ts_forceindex",    
      'actions_conf'  : { "entry_exit" :  
                            { 'model'    : "forceindex",
                              'type'     : "ta",
                              'obj_args' : { 'window' : 39 },
                              'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                              'exit_policy_args'   : { 'lastn_match' : 1 },
                            },
                        }  } )

# TS #11

tsConfDat.addTSConf(\
   ts_conf_dict = { 
      'ts_unique_tag' : "ts_mfi",    
      'actions_conf'  : { "entry_exit" :  
                            { 'model'    : "mfi",
                              'type'     : "ta",
                              'obj_args' : { 'window' : 14, 'long_slope_win' : 15, 'short_slope_win' : 15 },
                              'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                              'exit_policy_args'   : { 'lastn_match' : 1 },
                            },
                        }  } )
In [ ]:
taRegisterItems = [ ]
tsActionGen = TradeStrategyActionGenerator()

for trade_asset in portfolio_trade_assets :
    
    num_ts = len(tsConfDat.name_list) + 1  # adding the composite  trade strategy
    
    for i in range( num_ts ) :

        if i <= num_ts - 2:
            # *** Trade Strategy 

            actionDatItem  = tsConfDat.getTSConfigDataForItem(item_num = i )
            ts_unique_name = actionDatItem.name_list[0]
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = actionDatItem,
                                                     pipelineMng       = None )
        else :
            # Composite Trade Strategy 
            
            ts_unique_name = "all"            
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = tsConfDat,
                                                     pipelineMng       = None )

        ts_model = TradeStrategyBaseModelPersist(\
                        trade_asset               = trade_asset,
                        ts_marketdat_mng          = ts_marketdat_mng,
                        ts_enter                  = trade_enter_set,
                        ts_exit                   = trade_exit_set,                       
                        model_type                = ts_unique_name,
                        model_version             = "1.0",
                        market_data_period        = MarketDataPeriod.Day,
                    ) 

        # *** Trade Strategy Investment Manager 

        taInvMng = TradingAssetInvMngBase(\
                                        trade_asset                = trade_asset,
                                        minPeriodsBetweenTrades    = 1,
                                        initInvestment             = 1000000.0, 
                                        capPercentToInvestPerTrade = 100.0,
                                        minInvestPercent           = 5.0,
                                        min_account_balance        = 1000.0 )

        # *** Trade Register Item
        # *** This object has all configuration defined to execute a given trade strategy,
        # *** It can be executed individually in backtest or as part of a portfolio

        ta_registered_item = TradingAssetRegisterItem(\
                trade_name                    = "{0}_{1}".format(ts_unique_name, trade_asset), 
                ts_model                      = ts_model,
                tradingExecutionType          = TradingAssetExecutionType.Simulation,
                tradingBrokerObj              = brokerTradingObj,
                tradingAssetInvMngObj         = taInvMng )  

        taRegisterItems.append(ta_registered_item)
In [111]:
print("Number of configured TA Register Items : ", len(taRegisterItems ))
Number of configured TA Register Items :  36
Portfolio Investment Manager
In [112]:
# *** Porttfolio Investment Manager across all individual trade strategies investment managers
# *** Role: 
# ***    1) Managed investment funds across n number of trade strategies
# ***    2) Rebalance portfolio periodically or never
# ***    3) Portfolio Policy Weights 
# ***          equal weights (default)
# ***          MinimumVariance
# ***          User defined 
# ***    4) Track Portfolio level returns and metrics
# ***          Individual Trade Strategies return and metrics tracked through their 
# ***          investment managers
# ***          Portfolio funds are split across each trade strategy investment manager based on the
# ***          portfolio weights

portfInvMng = PortfolioInvMng(\
                  name                       = "Portfolio Inv. Manager for US-Indexes - Distinct TechAnal TS",
                  initInvestment             = 2000000.0 * ( len(taRegisterItems) + 3),  # 200K/trade-strag
                  portfRebalanceFreq         = PortfolioRebalanceFrequency.Never,
                  portfRebalancePeriods      = 1,
                  minInvestPercent           = 5.0,
                  min_account_balance        = 1000.0,     
                  minPeriodsBetweenTrades    = 1,
                  capPercentToInvestPerTrade = 100.0 )
Trade Register Items Portfolio
In [113]:
# *** Set of Trade Register Items
#
# Configuration Summary:
#    - Each set has 1 to n trade register items as previously described 
#    - Optionally add long only trade strategies for all unique trade assets in the
#      portfolio 
#           - (Dow, Nasdaq, and S&P 500 for this portfolio) in this example
#           - Might be useful for bench marking trade strategies
#    - Each set has one Investment Portfolio Manager
#       - portfolio funds allocated per portfolio policy rules and re-balanced (if defined), 
#         across all trade strategies


portf_registered_obj = PortfolioRegisterItem(\
                        name                 = "Portfolio of US-Indexes with Distinct TechAnal & Long strategies",
                        taRegisterItems      = taRegisterItems,
                        portfolioInvMngObj   = portfInvMng,
                        tradingExecutionType = TradingAssetExecutionType.Simulation,
                        add_long_only_ts     = True )
2021-10-28 16:41:49,255 [INFO] root: *** Adding long only trade strategies for : {'^GSPC', '^IXIC', '^DJI'}
Execute Backtest
In [114]:
tsExecuteEngine = BacktestExecution( \
                    name = "Backtest for Portfolio of Distinct TechAnal & Long Strategies",
                    timePeriod = DatasetDef(datasetType = DatasetType.Testing,
                                            strBegDate = "2006-01-01", 
                                            strEndDate = "2010-12-31" ),
                    trade_asset_registered_item = portf_registered_obj )
In [ ]:
tsExecuteEngine.evaluate()
Backtest Metrics
Execution & Investment Metrics
In [116]:
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
        'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']]
Out[116]:
TA_Reg_Name Is_Portfolio Num_Trades_Completed Init_Capital Final_Capital Cum_Return Backtest_Status
0 Portfolio of US-Indexes with Distinct TechAnal... Yes 3885 78000000.0 8.914324e+07 0.142862 Completed
1 ts_sma_1_^DJI No 27 2000000.0 3.259475e+06 0.629737 Completed
2 ts_sma_2_^DJI No 21 2000000.0 2.715084e+06 0.357542 Completed
3 ts_bb_^DJI No 230 2000000.0 2.425231e+06 0.212616 Completed
4 ts_macd_^DJI No 107 2000000.0 2.034301e+06 0.017151 Completed
5 ts_rsi_^DJI No 48 2000000.0 2.665718e+06 0.332859 Completed
6 ts_srsi_^DJI No 208 2000000.0 1.628879e+06 -0.185561 Completed
7 ts_adx_^DJI No 97 2000000.0 2.446447e+06 0.223224 Completed
8 ts_kama_^DJI No 19 2000000.0 2.527645e+06 0.263822 Completed
9 ts_tsi_^DJI No 58 2000000.0 2.140794e+06 0.070397 Completed
10 ts_forceindex_^DJI No 77 2000000.0 1.792767e+06 -0.103617 Completed
11 ts_mfi_^DJI No 182 2000000.0 2.043748e+06 0.021874 Completed
12 all_^DJI No 181 2000000.0 2.364100e+06 0.182050 Completed
13 ts_sma_1_^IXIC No 28 2000000.0 3.096447e+06 0.548224 Completed
14 ts_sma_2_^IXIC No 23 2000000.0 2.653684e+06 0.326842 Completed
15 ts_bb_^IXIC No 201 2000000.0 1.750279e+06 -0.124861 Completed
16 ts_macd_^IXIC No 125 2000000.0 1.611098e+06 -0.194451 Completed
17 ts_rsi_^IXIC No 42 2000000.0 1.653055e+06 -0.173473 Completed
18 ts_srsi_^IXIC No 229 2000000.0 1.261079e+06 -0.369461 Completed
19 ts_adx_^IXIC No 98 2000000.0 3.130286e+06 0.565143 Completed
20 ts_kama_^IXIC No 22 2000000.0 2.632824e+06 0.316412 Completed
21 ts_tsi_^IXIC No 55 2000000.0 2.302845e+06 0.151422 Completed
22 ts_forceindex_^IXIC No 84 2000000.0 2.625037e+06 0.312519 Completed
23 ts_mfi_^IXIC No 183 2000000.0 1.670405e+06 -0.164798 Completed
24 all_^IXIC No 197 2000000.0 3.222387e+06 0.611194 Completed
25 ts_sma_1_^GSPC No 28 2000000.0 2.676540e+06 0.338270 Completed
26 ts_sma_2_^GSPC No 22 2000000.0 2.906510e+06 0.453255 Completed
27 ts_bb_^GSPC No 219 2000000.0 2.725456e+06 0.362728 Completed
28 ts_macd_^GSPC No 169 2000000.0 1.607609e+06 -0.196196 Completed
29 ts_rsi_^GSPC No 55 2000000.0 2.560077e+06 0.280038 Completed
30 ts_srsi_^GSPC No 231 2000000.0 1.097250e+06 -0.451375 Completed
31 ts_adx_^GSPC No 96 2000000.0 2.403768e+06 0.201884 Completed
32 ts_kama_^GSPC No 15 2000000.0 2.867114e+06 0.433557 Completed
33 ts_tsi_^GSPC No 66 2000000.0 1.832013e+06 -0.083994 Completed
34 ts_forceindex_^GSPC No 72 2000000.0 2.156671e+06 0.078335 Completed
35 ts_mfi_^GSPC No 169 2000000.0 1.331140e+06 -0.334430 Completed
36 all_^GSPC No 198 2000000.0 2.844191e+06 0.422095 Completed
37 Long-Only Trade Strategy for ^GSPC No 1 2000000.0 1.982412e+06 -0.008794 Completed
38 Long-Only Trade Strategy for ^IXIC No 1 2000000.0 2.364535e+06 0.182267 Completed
39 Long-Only Trade Strategy for ^DJI No 1 2000000.0 2.134338e+06 0.067169 Completed
Performance Metrics
In [118]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ]
Out[118]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
0 Portfolio of US-Indexes with Distinct TechAnal... Yes 2006-01-04 2010-12-31 1.0 0.14 0.03 0.33 -0.1 0.04 -0.03
1 ts_sma_1_^DJI No ts_sma_1 ^DJI 2006-01-04 2010-12-31 0.98 0.63 0.1 0.6 -0.24 0.07 -0.07
2 ts_sma_2_^DJI No ts_sma_2 ^DJI 2006-01-04 2010-12-31 0.99 0.36 0.06 0.44 -0.2 0.06 -0.06
3 ts_bb_^DJI No ts_bb ^DJI 2006-01-04 2010-12-31 0.7 0.21 0.04 0.3 -0.22 0.11 -0.08
4 ts_macd_^DJI No ts_macd ^DJI 2006-01-04 2010-12-31 0.93 0.02 0.0 0.12 -0.24 0.07 -0.08
5 ts_rsi_^DJI No ts_rsi ^DJI 2006-01-04 2010-12-31 0.09 0.33 0.06 0.76 -0.08 0.11 -0.03
6 ts_srsi_^DJI No ts_srsi ^DJI 2006-01-04 2010-12-31 0.5 -0.19 -0.04 -0.22 -0.35 0.08 -0.11
7 ts_adx_^DJI No ts_adx ^DJI 2006-01-04 2010-12-31 0.89 0.22 0.04 0.32 -0.21 0.07 -0.07
8 ts_kama_^DJI No ts_kama ^DJI 2006-01-04 2010-12-31 1.0 0.26 0.05 0.36 -0.27 0.05 -0.05
9 ts_tsi_^DJI No ts_tsi ^DJI 2006-01-04 2010-12-31 0.96 0.07 0.01 0.17 -0.25 0.07 -0.07
10 ts_forceindex_^DJI No ts_forceindex ^DJI 2006-01-04 2010-12-31 0.92 -0.1 -0.02 -0.02 -0.31 0.06 -0.08
11 ts_mfi_^DJI No ts_mfi ^DJI 2006-01-04 2010-12-31 0.58 0.02 0.0 0.11 -0.31 0.07 -0.09
12 all_^DJI No all ^DJI 2006-01-04 2010-12-31 0.97 0.18 0.03 0.27 -0.22 0.08 -0.06
13 ts_sma_1_^IXIC No ts_sma_1 ^IXIC 2006-01-04 2010-12-31 0.98 0.55 0.09 0.51 -0.3 0.09 -0.07
14 ts_sma_2_^IXIC No ts_sma_2 ^IXIC 2006-01-04 2010-12-31 0.99 0.33 0.06 0.37 -0.31 0.09 -0.07
15 ts_bb_^IXIC No ts_bb ^IXIC 2006-01-04 2010-12-31 0.67 -0.12 -0.03 -0.02 -0.33 0.12 -0.07
16 ts_macd_^IXIC No ts_macd ^IXIC 2006-01-04 2010-12-31 0.92 -0.19 -0.04 -0.07 -0.31 0.08 -0.09
17 ts_rsi_^IXIC No ts_rsi ^IXIC 2006-01-04 2010-12-31 0.09 -0.17 -0.04 -0.34 -0.27 0.12 -0.07
18 ts_srsi_^IXIC No ts_srsi ^IXIC 2006-01-04 2010-12-31 0.52 -0.37 -0.09 -0.43 -0.43 0.09 -0.11
19 ts_adx_^IXIC No ts_adx ^IXIC 2006-01-04 2010-12-31 0.85 0.57 0.09 0.53 -0.27 0.09 -0.07
20 ts_kama_^IXIC No ts_kama ^IXIC 2006-01-04 2010-12-31 1.0 0.32 0.06 0.37 -0.3 0.08 -0.07
21 ts_tsi_^IXIC No ts_tsi ^IXIC 2006-01-04 2010-12-31 0.96 0.15 0.03 0.24 -0.33 0.08 -0.06
22 ts_forceindex_^IXIC No ts_forceindex ^IXIC 2006-01-04 2010-12-31 0.92 0.31 0.06 0.36 -0.31 0.09 -0.07
23 ts_mfi_^IXIC No ts_mfi ^IXIC 2006-01-04 2010-12-31 0.58 -0.16 -0.04 -0.1 -0.39 0.09 -0.08
24 all_^IXIC No all ^IXIC 2006-01-04 2010-12-31 0.98 0.61 0.1 0.55 -0.25 0.08 -0.06
25 ts_sma_1_^GSPC No ts_sma_1 ^GSPC 2006-01-04 2010-12-31 0.98 0.34 0.06 0.39 -0.26 0.09 -0.07
26 ts_sma_2_^GSPC No ts_sma_2 ^GSPC 2006-01-04 2010-12-31 0.99 0.45 0.08 0.48 -0.25 0.07 -0.06
27 ts_bb_^GSPC No ts_bb ^GSPC 2006-01-04 2010-12-31 0.68 0.36 0.06 0.4 -0.24 0.12 -0.09
28 ts_macd_^GSPC No ts_macd ^GSPC 2006-01-04 2010-12-31 0.89 -0.2 -0.04 -0.09 -0.34 0.08 -0.09
29 ts_rsi_^GSPC No ts_rsi ^GSPC 2006-01-04 2010-12-31 0.08 0.28 0.05 0.64 -0.09 0.12 -0.08
30 ts_srsi_^GSPC No ts_srsi ^GSPC 2006-01-04 2010-12-31 0.49 -0.45 -0.11 -0.65 -0.48 0.09 -0.1
31 ts_adx_^GSPC No ts_adx ^GSPC 2006-01-04 2010-12-31 0.87 0.2 0.04 0.28 -0.28 0.09 -0.07
32 ts_kama_^GSPC No ts_kama ^GSPC 2006-01-04 2010-12-31 1.0 0.43 0.07 0.5 -0.25 0.06 -0.05
33 ts_tsi_^GSPC No ts_tsi ^GSPC 2006-01-04 2010-12-31 0.94 -0.08 -0.02 0.02 -0.29 0.08 -0.07
34 ts_forceindex_^GSPC No ts_forceindex ^GSPC 2006-01-04 2010-12-31 0.92 0.08 0.02 0.18 -0.31 0.09 -0.07
35 ts_mfi_^GSPC No ts_mfi ^GSPC 2006-01-04 2010-12-31 0.61 -0.33 -0.08 -0.31 -0.54 0.09 -0.09
36 all_^GSPC No all ^GSPC 2006-01-04 2010-12-31 0.97 0.42 0.07 0.45 -0.26 0.08 -0.06
37 Long-Only Trade Strategy for ^GSPC No long ^GSPC 2006-01-04 2010-12-31 1.0 -0.01 -0.0 0.12 -0.57 0.12 -0.09
38 Long-Only Trade Strategy for ^IXIC No long ^IXIC 2006-01-04 2010-12-31 1.0 0.18 0.03 0.26 -0.56 0.12 -0.09
39 Long-Only Trade Strategy for ^DJI No long ^DJI 2006-01-04 2010-12-31 1.0 0.07 0.01 0.17 -0.54 0.11 -0.08
In [119]:
tsExecuteEngine.getSummaryMetrics().T.head(60)
Out[119]:
0 1 2 3 4 5 6 7 8 9 ... 30 31 32 33 34 35 36 37 38 39
ta_reg_item_name Portfolio of US-Indexes with Distinct TechAnal... ts_sma_1_^DJI ts_sma_2_^DJI ts_bb_^DJI ts_macd_^DJI ts_rsi_^DJI ts_srsi_^DJI ts_adx_^DJI ts_kama_^DJI ts_tsi_^DJI ... ts_srsi_^GSPC ts_adx_^GSPC ts_kama_^GSPC ts_tsi_^GSPC ts_forceindex_^GSPC ts_mfi_^GSPC all_^GSPC Long-Only Trade Strategy for ^GSPC Long-Only Trade Strategy for ^IXIC Long-Only Trade Strategy for ^DJI
ta_reg_item_id None None None None None None None None None None ... None None None None None None None None None None
is_portfolio Yes No No No No No No No No No ... No No No No No No No No No No
model_type ts_sma_1 ts_sma_2 ts_bb ts_macd ts_rsi ts_srsi ts_adx ts_kama ts_tsi ... ts_srsi ts_adx ts_kama ts_tsi ts_forceindex ts_mfi all long long long
trade_asset ^DJI ^DJI ^DJI ^DJI ^DJI ^DJI ^DJI ^DJI ^DJI ... ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^IXIC ^DJI
test_period_len_days 1825 1825 1825 1825 1825 1825 1825 1825 1825 1825 ... 1825 1825 1825 1825 1825 1825 1825 1825 1825 1825
tr_period_len_days 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
val_period_len_days 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
index Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy ... Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy
Start Period 2006-01-04 2006-01-04 2006-01-04 2006-01-04 2006-01-04 2006-01-04 2006-01-04 2006-01-04 2006-01-04 2006-01-04 ... 2006-01-04 2006-01-04 2006-01-04 2006-01-04 2006-01-04 2006-01-04 2006-01-04 2006-01-04 2006-01-04 2006-01-04
End Period 2010-12-31 2010-12-31 2010-12-31 2010-12-31 2010-12-31 2010-12-31 2010-12-31 2010-12-31 2010-12-31 2010-12-31 ... 2010-12-31 2010-12-31 2010-12-31 2010-12-31 2010-12-31 2010-12-31 2010-12-31 2010-12-31 2010-12-31 2010-12-31
Risk-Free Rate 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
Time in Market 1.0 0.98 0.99 0.7 0.93 0.09 0.5 0.89 1.0 0.96 ... 0.49 0.87 1.0 0.94 0.92 0.61 0.97 1.0 1.0 1.0
Cumulative Return 0.14 0.63 0.36 0.21 0.02 0.33 -0.19 0.22 0.26 0.07 ... -0.45 0.2 0.43 -0.08 0.08 -0.33 0.42 -0.01 0.18 0.07
CAGR% 0.03 0.1 0.06 0.04 0.0 0.06 -0.04 0.04 0.05 0.01 ... -0.11 0.04 0.07 -0.02 0.02 -0.08 0.07 -0.0 0.03 0.01
Sharpe 0.33 0.6 0.44 0.3 0.12 0.76 -0.22 0.32 0.36 0.17 ... -0.65 0.28 0.5 0.02 0.18 -0.31 0.45 0.12 0.26 0.17
Sortino 0.47 0.88 0.63 0.45 0.17 2.05 -0.29 0.46 0.52 0.24 ... -0.88 0.42 0.73 0.02 0.25 -0.44 0.66 0.16 0.37 0.24
Sortino/√2 0.33 0.62 0.45 0.32 0.12 1.45 -0.21 0.32 0.37 0.17 ... -0.63 0.3 0.51 0.02 0.18 -0.31 0.47 0.12 0.26 0.17
Max Drawdown -0.1 -0.24 -0.2 -0.22 -0.24 -0.08 -0.35 -0.21 -0.27 -0.25 ... -0.48 -0.28 -0.25 -0.29 -0.31 -0.54 -0.26 -0.57 -0.56 -0.54
Longest DD Days 594 360 397 695 786 848 1814 661 879 534 ... 1814 703 594 1043 770 794 596 1178 1156 1178
Volatility (ann.) 0.09 0.19 0.17 0.19 0.2 0.08 0.14 0.18 0.17 0.19 ... 0.16 0.2 0.17 0.2 0.2 0.2 0.2 0.25 0.26 0.23
Calmar 0.27 0.44 0.31 0.18 0.01 0.77 -0.12 0.2 0.18 0.05 ... -0.24 0.13 0.3 -0.06 0.05 -0.15 0.28 -0.0 0.06 0.02
Skew 0.01 0.02 -0.03 0.81 0.06 12.67 -1.04 0.16 -0.05 0.25 ... -0.14 0.48 0.04 0.34 0.25 -0.04 0.33 0.02 0.05 0.26
Kurtosis 6.16 4.7 2.99 17.46 5.79 246.79 28.06 5.44 2.51 4.51 ... 20.39 5.52 2.48 4.9 5.57 12.01 4.1 8.88 6.4 9.55
Expected Daily % 0.0 0.0 0.0 0.0 0.0 0.0 -0.0 0.0 0.0 0.0 ... -0.0 0.0 0.0 -0.0 0.0 -0.0 0.0 -0.0 0.0 0.0
Expected Monthly % 0.0 0.01 0.01 0.0 0.0 0.0 -0.0 0.0 0.0 0.0 ... -0.01 0.0 0.01 -0.0 0.0 -0.01 0.01 -0.0 0.0 0.0
Expected Yearly % 0.03 0.1 0.06 0.04 0.0 0.06 -0.04 0.04 0.05 0.01 ... -0.11 0.04 0.07 -0.02 0.02 -0.08 0.07 -0.0 0.03 0.01
Kelly Criterion 0.03 0.06 0.04 0.03 0.01 0.25 -0.03 0.03 0.03 0.02 ... -0.1 0.03 0.04 0.0 0.02 -0.04 0.04 0.01 0.03 0.02
Risk of Ruin 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
Daily Value-at-Risk -0.01 -0.02 -0.02 -0.02 -0.02 -0.01 -0.01 -0.02 -0.02 -0.02 ... -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.03 -0.03 -0.02
Expected Shortfall (cVaR) -0.01 -0.02 -0.02 -0.02 -0.02 -0.01 -0.01 -0.02 -0.02 -0.02 ... -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.03 -0.03 -0.02
Gain/Pain Ratio 0.07 0.12 0.08 0.08 0.02 0.91 -0.06 0.06 0.07 0.03 ... -0.17 0.06 0.09 0.0 0.03 -0.08 0.09 0.02 0.05 0.03
Gain/Pain (1M) 0.45 0.97 0.56 0.46 0.13 2.33 -0.18 0.36 0.39 0.18 ... -0.53 0.36 0.59 0.02 0.19 -0.25 0.6 0.14 0.26 0.21
Payoff Ratio 0.91 0.99 0.97 1.17 1.04 1.75 0.88 0.98 0.99 0.92 ... 0.95 1.04 1.01 0.94 0.95 1.0 0.99 0.85 0.88 0.88
Profit Factor 1.07 1.12 1.08 1.08 1.02 1.91 0.94 1.06 1.07 1.03 ... 0.83 1.06 1.09 1.0 1.03 0.92 1.09 1.02 1.05 1.03
Common Sense Ratio 1.09 1.08 1.04 1.42 1.04 NaN 0.92 1.06 1.0 1.02 ... 0.72 1.09 1.08 0.94 0.98 0.87 1.08 0.95 0.99 0.99
CPC Index 0.52 0.59 0.56 0.6 0.53 1.74 0.43 0.54 0.55 0.5 ... 0.37 0.56 0.57 0.49 0.51 0.44 0.56 0.48 0.5 0.49
Tail Ratio 1.03 0.96 0.96 1.32 1.01 NaN 0.98 1.0 0.94 0.99 ... 0.87 1.03 0.99 0.94 0.95 0.94 1.0 0.93 0.94 0.96
Outlier Win Ratio 4.47 4.33 3.86 7.59 4.91 21.93 10.41 4.91 3.93 4.65 ... 10.74 5.37 3.85 4.9 5.0 8.68 4.38 4.66 4.44 4.29
Outlier Loss Ratio 4.44 3.81 3.68 4.43 4.06 1.49 3.43 3.67 3.57 3.7 ... 3.6 3.86 3.73 3.77 3.81 3.86 3.86 4.43 3.89 4.44
MTD 0.03 0.05 0.05 0.0 -0.01 0.0 0.02 -0.0 0.05 -0.01 ... -0.01 0.01 0.07 0.03 0.07 -0.04 0.02 0.07 0.06 0.05
3M 0.05 0.07 0.07 0.02 -0.03 0.01 0.01 0.05 0.07 0.0 ... -0.04 0.04 0.1 0.06 0.1 -0.02 0.05 0.1 0.12 0.07
6M -0.02 -0.01 -0.08 0.02 -0.02 0.01 0.02 0.01 -0.14 -0.03 ... -0.06 -0.02 0.02 -0.02 -0.0 -0.07 -0.02 0.22 0.26 0.18
YTD 0.02 0.04 -0.1 -0.01 0.06 0.06 0.03 0.09 -0.15 -0.01 ... -0.08 0.17 0.04 0.03 0.14 -0.17 0.13 0.13 0.17 0.11
1Y 0.01 0.03 -0.11 -0.0 0.05 0.06 0.02 0.08 -0.16 -0.03 ... -0.09 0.16 0.03 0.02 0.12 -0.17 0.12 0.12 0.16 0.1
3Y (ann.) 0.06 0.16 0.11 0.01 0.02 0.13 -0.03 0.1 0.14 0.08 ... -0.13 0.12 0.21 0.03 0.09 -0.14 0.2 -0.05 -0.0 -0.05
5Y (ann.) 0.03 0.1 0.06 0.04 0.0 0.06 -0.04 0.04 0.05 0.01 ... -0.11 0.04 0.07 -0.02 0.02 -0.08 0.07 -0.0 0.03 0.01
10Y (ann.) 0.03 0.1 0.06 0.04 0.0 0.06 -0.04 0.04 0.05 0.01 ... -0.11 0.04 0.07 -0.02 0.02 -0.08 0.07 -0.0 0.03 0.01
All-time (ann.) 0.03 0.1 0.06 0.04 0.0 0.06 -0.04 0.04 0.05 0.01 ... -0.11 0.04 0.07 -0.02 0.02 -0.08 0.07 -0.0 0.03 0.01
Best Day 0.04 0.07 0.06 0.11 0.07 0.11 0.08 0.07 0.05 0.07 ... 0.09 0.09 0.06 0.08 0.09 0.09 0.08 0.12 0.12 0.11
Worst Day -0.03 -0.07 -0.06 -0.08 -0.08 -0.03 -0.11 -0.07 -0.05 -0.07 ... -0.1 -0.07 -0.05 -0.07 -0.07 -0.09 -0.06 -0.09 -0.09 -0.08
Best Month 0.08 0.14 0.11 0.08 0.2 0.18 0.17 0.14 0.1 0.13 ... 0.06 0.15 0.11 0.15 0.16 0.25 0.14 0.09 0.12 0.09
Worst Month -0.04 -0.09 -0.11 -0.1 -0.11 -0.03 -0.1 -0.11 -0.09 -0.13 ... -0.09 -0.07 -0.1 -0.12 -0.11 -0.28 -0.07 -0.17 -0.18 -0.14
Best Year 0.08 0.29 0.31 0.12 0.09 0.24 0.03 0.16 0.35 0.28 ... -0.03 0.17 0.38 0.08 0.14 0.05 0.31 0.23 0.44 0.19
Worst Year -0.06 -0.08 -0.1 -0.06 -0.13 -0.04 -0.14 -0.11 -0.16 -0.15 ... -0.2 -0.16 -0.2 -0.15 -0.19 -0.17 -0.19 -0.38 -0.41 -0.34
Avg. Drawdown -0.02 -0.03 -0.04 -0.04 -0.07 -0.02 -0.35 -0.05 -0.03 -0.05 ... -0.48 -0.06 -0.03 -0.19 -0.06 -0.06 -0.05 -0.03 -0.05 -0.03
Avg. Drawdown Days 65 35 46 58 127 138 1814 104 37 80 ... 1814 104 40 605 128 88 60 52 67 46
Recovery Factor 1.41 2.67 1.77 0.96 0.07 4.32 -0.53 1.06 0.98 0.28 ... -0.94 0.71 1.73 -0.29 0.26 -0.62 1.59 -0.02 0.33 0.13
Ulcer Index 1.05 1.04 1.06 inf inf inf 1.06 1.04 1.06 1.06 ... 1.05 1.05 1.05 1.06 1.06 inf 1.06 1.05 1.05 1.05
Avg. Up Month 0.01 0.03 0.03 0.02 0.04 0.03 0.03 0.04 0.03 0.03 ... 0.02 0.04 0.03 0.04 0.04 0.03 0.04 0.03 0.05 0.03

60 rows × 40 columns

Persist Backtest to DB (optional )
In [ ]:
session.add( tsExecuteEngine )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst)
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")

Portfolio F

  1. Portfolio F: Long and Multiple Configured AI-Modeled Trade Strategies for US Indixes

    Description:

     1. Portfolio with 30 trading strategies
     2. $200,000/strategy, Total Budget = $6M
     3. No-Rebalance during the backtest 
     4. 100% capital invested
     5. Portfolio investment using equal weights for each trade strategy
    
    

    Trade Strategies:

     1. Three trade strategies: Nasdaq, S&P 500, and DOW Jones with buy-and-hold
     2. 24 trade strategies: Nasdaq, S&P 500, and DOW Jones using the following AI-Models
        and corresponding configurations:
    
                                                        Trading AI-Models
    
           Parameter                 #1      #2      #3        #4          #5        #6        #7
    
        ai-model                    GRU    LSTM Conv1d-GRU Conv1d-LSTM  Wavenet  Wavenet-GRU  GRU
        epochs                       20      20      20        20          20        20        20
        no neurons layer 1           20      20      20        20           -        20        20
        no neurons layer 2           20      20      20        20           -        20        20
        time series length           50      50      50        50          50        50        40         
        no predictions ahead          5       5       5         5           5         5         3
        extend trade dyn            Yes     Yes     Yes       Yes         Yes       Yes       Yes
        re_evalaute_exit_dyn        Yes     Yes     Yes       Yes         Yes       Yes       Yes
        enter_if_last_nmatch          1       1       1         1           1         1         1
        enter_if_cross_over_sig      No      No      No        No          No        No        No
        exit_if_last_nmatch           1       1       1         1           1         1         1
    
           Parameter                 #8              
    
        ai-model                 Wavenet-LSTM 
        epochs                        20           
        no neurons layer 1            20           
        no neurons layer 2            20           
        time series length            50                    
        no predictions ahead           5            
        extend trade dyn             Yes          
        re_evalaute_exit_dyn         Yes          
        enter_if_last_nmatch           1            
        enter_if_cross_over_sig       No           
        exit_if_last_nmatch            1            
    
        Note: 
          - the parameters "no neurons layer 1" and "no neurons layer 2" are only applicable to 
            AI Models that have GRU or LSTM layers. 
          - Conv1d is a convulation layer in one dimension (configured with 40 filters )
          - Wavenet is an AI Architectured based on a set of Convolutional Layers
    
     3. Three trade strategies: Nasdaq, S&P 500, and DOW Jones using the following Composite 
        model configuration: 
    
         - A Composite Trade Strategy based on all the AI Trading Models configured above
    
         - The Set Entry cofiguration rules are: 
           a. Majority Voting (default)
           b. Enter a trade if the last n voting decisions are the same, set to 1 (default )
           c. Enter a trade if there is cross-over signaled after applying rules a) and b), 
              set to False (default)
    
         - The Set Exit configuration rules are: 
           a. Majority Voting (Default)
               - Exit a long trade if the percent of Trading AI Models signaled an exit for a long position
                  is greater that the percent signaling no-exit 
               - Exit a short trade if the percent of Trading AI Models signaled an exit for a short position
                  is greater that the percent signaling no-exit 
           b. Exit a trade if the last n exit decisions are the same, set to 1 (default )
    
    

    Backtest:

     1. Type: regular
    
     2. AI Models Fit Date Ranges
         1. Training Period: 
             1. Begin Date = 2002-01-01 
             2. End Date   = 2006-12-31  
         2. Validation Period: 
             1. Begin Date = 2007-01-01 
             2. End Date   = 2008-06-30 
    
     3. Test Period: 
         1. Begin Date = 2009-01-01 
         2. End Date   = 2009-12-31         
Portfolio Trade Assets
In [120]:
portfolio_trade_assets   = [ "^DJI", "^IXIC", "^GSPC" ]
Market Data Manager
In [121]:
dirPathMarketData = '/Users/gustavozambrana/Google Drive/Python/Projects/Trade_Engine/Data/US_Market_Indixes'

supportedTradeAssets   = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str           = "2000-01-01"
end_date_str           = None

ts_marketdat_mng = TradeStrategyMarketDataMng(\
        marketDataProviderName = "yahoofinance",
        supportedTradeAssets   = supportedTradeAssets,
        stock_price_col_name   = "Adj Close",
        fileNameMarketData     = "US_Indixes_And_ETFs_MrkData",
        dirPathMarketData      = dirPathMarketData,
        beg_date_str           = beg_date_str,
        end_date_str           = end_date_str,
        interval               = "1d"  ) 
2021-10-28 18:04:03,558 [INFO] root: Found previous Market data previously loaded to specified file and dir.
Pipeline Data Manager
In [122]:
ts_model_pipline_mng_f = TradeStrategyModelPipelineDataMng(\
                            tsMarketDataMng    = ts_marketdat_mng,
                            package            = "trade_engine.model.ai.WaveNet_RNN_AI_PipelineBuilder",
                            model_class_name   = "WaveNet_RNN_AI_PipelineBuilder",
                            fileNameMarketData = "WaveNet_RNN_AI_Pipeline_Data_Portf_D",
                            forceCreatePipelineData = True,
                            dirPathMarketData  = dirPathMarketData )
Simulation Broker
In [123]:
brokerTradingObj = SimBrokerTrading()
Trade Strategies, Trade Investment Manager, and Trade Asset Register Items
In [125]:
# Define Metadata for several Trading AI-Models for several Trade Strategies in the portfolio and one
# Trade Strategy based on a composite set of all Trading AI-Models. The composite trade strategy
# uses Majority Voting for entering and exiting a trade (default setting)

# The configuraiton data for each Trade Strategy is defined via a JSON/dict, and 
# they are added to the TradeStrategyConfigData() object
# 
# This configuration method is a short-cut when creating many trade strategies in a portfolio, or 
# a composite of many trade strategies. The JSON format follows the general format:
#
# *** Trade Strategy Config:
#
# 1. ts_unique_tag : unique tag to identify a trade strategy in a set
# 2. actions_conf : dict, 
#       Description: contains the configuration data for each action in a trade strategy, only
#                    the "entry_exit", sub-tag is required
#       Child tags:
#             "entry_exit" : required
#             "stop_lost"  : optional
#             "pos_sizing" : optional
#             "pyramiding" : optional
# 3. The format of each child-tag/action follows the same parameters as when defined via the class,
# 4. obj_args : custom set of parameters passed to the defined model defined via the model tag, this
#               is a dynamic set of parameters and specific to each model, some share common inputs.
#
#    Supported built-in models, for the entry_exit action:
#        [ "sma", "bb", "macd", "rsi", "srsi", "adx", "kama", "tsi",
#          "forceindex", "mfi", 'conv1d_gru', 'conv1d_lstm', 'wavenet', 
#          'wavenet_gru', 'wavenet_lstm', 'lstm', 'gru' ]
#
#    Custom models can be added via a custom function. The second strategy in the configuration
#    below ('ts_unique_tag' : "ts_gru_1") , defines the "custom_create_func" tag and sets equal to
#    "create_actions_ai_ts_model", this function should be already defined or imported. Thus for
#    trade strategy #2, the user custom function is used. Note, that for trade strategy: ts_gru_2
#    the model is also set to "gru", but in this case it is using the built-in gru model.
#    The actual implementantions for all supported models are included in this Jupyter Notebook, at
#    the beg. of this portfolio example, and a user can copy and altered as they see fit, it would
#    affect the built-in functions, which are scope in a pythong package.
#
#
# *** Trade Strategy Set Config:
#
# There is only one set configuration, and it is defined to apply policies on how to treat the 
# set actions, this configuration is optional, and defaults for each action are defined below
#
# "entry" : optional
#     Defines the policy to drive the trade decision to follow from the set. As explained in earlier 
#     examples. 
#     Default policy parameters are:
#           Majority Voting, 
#           incNoInvestInVotingDec = False, 
#           lastn_match = 1
#           cross_over_signal_for_trading
#
# "exit" : optional
#     Defines the policy to drive the exit decision to follow from the set. As explained in earlier 
#     examples. 
#     Default policy parameters are:
#           Majority Voting, 
#           lastn_match = 1
#

tsConfDat = TradeStrategyConfigData()

# Set Config

tsConfDat.tsSetConfig(\
    ts_set_conf_dict = 
           { 'set_actions_conf' : 
                      { "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
                        "exit"  : { 'votingPolicy' : 1, 
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1 } 
                      }
           } )
           
# TS #1

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_gru_1", 
    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "gru",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'         : 20 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 1, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },

                               "stop_lost" :
                                    { 'model'    : "fix_perc",
                                      'type'     : "ta",
                                      'obj_args' : { 'long_stop_los_per' : 5, 'short_stop_los_per'    : 5 }  } 
                             },
                    }  )

# TS #2

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_lstm", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'         : 50,   'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn'   : True,
                                                 'epochs'          : 20 }  
                                }
                            } }  )
# TS #3
    
tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_conv1d_gru", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "conv1d_gru",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'   : 50,   'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'          : 20 }  
                                }
                            } }  )

# TS #4

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_conv1d_lstm", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "conv1d_lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'  : 50,   'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'          : 20 }  
                                }
                            } }  )

# TS #5

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_wavenet", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "wavenet",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'      : 50,   'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'          : 20 }  
                                }
                            } }  )

# TS #6

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_wavenet_gru", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "wavenet_gru",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'      : 50,   'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'          : 20 }  
                                }
                            } }  )

# TS #7
tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_wavenet_lstm", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "wavenet_lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'      : 50,   'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'          : 20 }  
                                }
                            } }  )

# TS #8
tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_gru_2", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "gru",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'          : 40,   'no_neurons_lay1'    : 20,
                                         'no_neurons_lay2' : 20,   'pred_ahead_periods' : 3,
                                         'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                         'epochs'          : 20 }  
                                }
                            } }  )
In [126]:
taRegisterItems = [ ]
tsActionGen = TradeStrategyActionGenerator()

for trade_asset in portfolio_trade_assets :
    
    num_ts = len(tsConfDat.name_list) + 1  # adding the composite  trade strategy
    
    for i in range( num_ts ) :

        if i <= num_ts - 2:
            # *** Trade Strategy 

            actionDatItem  = tsConfDat.getTSConfigDataForItem(item_num = i )
            ts_unique_name = actionDatItem.name_list[0]
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = actionDatItem,
                                                     pipelineMng       = ts_model_pipline_mng_f )
        else :
            # Composite Trade Strategy 
            
            ts_unique_name = "all"            
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = tsConfDat,
                                                     pipelineMng       = ts_model_pipline_mng_f )

        ts_model = TradeStrategyBaseModelPersist(\
                        trade_asset               = trade_asset,
                        ts_marketdat_mng          = ts_marketdat_mng,
                        ts_enter                  = trade_enter_set,
                        ts_exit                   = trade_exit_set,                       
                        model_type                = ts_unique_name,
                        model_version             = "1.0",
                        market_data_period        = MarketDataPeriod.Day,
                    ) 

        # *** Trade Strategy Investment Manager 

        taInvMng = TradingAssetInvMngBase(\
                                        trade_asset                = trade_asset,
                                        minPeriodsBetweenTrades    = 1,
                                        initInvestment             = 1000000.0, 
                                        capPercentToInvestPerTrade = 100.0,
                                        minInvestPercent           = 5.0,
                                        min_account_balance        = 1000.0 )

        # *** Trade Register Item
        # *** This object has all configuration defined to execute a given trade strategy,
        # *** It can be executed individually in backtest or as part of a portfolio

        ta_registered_item = TradingAssetRegisterItem(\
                trade_name                    = "{0}_{1}".format(ts_unique_name, trade_asset), 
                ts_model                      = ts_model,
                tradingExecutionType          = TradingAssetExecutionType.Simulation,
                tradingBrokerObj              = brokerTradingObj,
                tradingAssetInvMngObj         = taInvMng )  

        taRegisterItems.append(ta_registered_item)
In [127]:
print("Number of configured Trade Asset Register Items: ", len(taRegisterItems) )
Number of configured Trade Asset Register Items:  27
Portfolio Investment Manager
In [128]:
# *** Porttfolio Investment Manager across all individual trade strategies investment managers
# *** Role: 
# ***    1) Managed investment funds across n number of trade strategies
# ***    2) Rebalance portfolio periodically or never
# ***    3) Portfolio Policy Weights 
# ***          equal weights (default)
# ***          MinimumVariance
# ***          User defined 
# ***    4) Track Portfolio level returns and metrics
# ***          Individual Trade Strategies return and metrics tracked through their 
# ***          investment managers
# ***          Portfolio funds are split across each trade strategy investment manager based on the
# ***          portfolio weights

portfInvMng = PortfolioInvMng(\
                  name                       = "Portfolio Inv. Manager for US-Indexes - Multiple-AI-Trading Models TS",
                  initInvestment             = 2000000.0 * ( len(taRegisterItems) + 3),  # 200K/trade-strag
                  portfRebalanceFreq         = PortfolioRebalanceFrequency.Never,
                  portfRebalancePeriods      = 1,
                  minInvestPercent           = 5.0,
                  min_account_balance        = 1000.0,     
                  minPeriodsBetweenTrades    = 1,
                  capPercentToInvestPerTrade = 100.0 )
Trade Register Items Portfolio
In [129]:
# *** Set of Trade Register Items
#
# Configuration Summary:
#    - Each set has 1 to n trade register items as previously described 
#    - Optionally add long only trade strategies for all unique trade assets in the
#      portfolio 
#           - (Dow, Nasdaq, and S&P 500 for this portfolio) in this example
#           - Might be useful for bench marking trade strategies
#    - Each set has one Investment Portfolio Manager
#       - portfolio funds allocated per portfolio policy rules and re-balanced (if defined), 
#         across all trade strategies


portf_registered_obj = PortfolioRegisterItem(\
                        name                 = "Portfolio F, US-Indexes with Mult-AI-Trading and Long strategies",
                        taRegisterItems      = taRegisterItems,
                        portfolioInvMngObj   = portfInvMng,
                        tradingExecutionType = TradingAssetExecutionType.Simulation,
                        add_long_only_ts     = True )
2021-10-28 18:10:04,111 [INFO] root: *** Adding long only trade strategies for : {'^GSPC', '^IXIC', '^DJI'}
Persist to DB (optional)
In [130]:
session.add( portf_registered_obj )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")
 done
Re-Store from DB (optional)
In [131]:
session.expunge_all()
del portf_registered_obj

for tsObj in session.query(PortfolioRegisterItem):  
    print(tsObj.name)
    if  tsObj.name  == "Portfolio F, US-Indexes with Mult-AI-Trading and Long strategies" :
        break

portf_registered_obj = tsObj
print(portf_registered_obj.id, portf_registered_obj.name)
2021-10-28 18:11:01,158 [INFO] root: PortfolioRegisterItem init called. 
2021-10-28 18:11:01,159 [INFO] root: PortfolioRegisterItem init called. 
2021-10-28 18:11:01,159 [INFO] root: PortfolioRegisterItem init called. 
2021-10-28 18:11:01,160 [INFO] root: PortfolioRegisterItem init called. 
2021-10-28 18:11:01,161 [INFO] root: PortfolioRegisterItem init called. 
2021-10-28 18:11:01,162 [INFO] root: PortfolioRegisterItem init called. 
Portfolio of US-Indexes using SMA and Long strategies
Portfolio of US-Indexes using LSTM and Long strategies
Portfolio of US-Indexes with Multiple-SMA and Long strategies
Portfolio of US-Indexes with Multiple-SMA and Long strategies
Portfolio of US-Indexes with Multiple-LSTM and Long strategies
Portfolio of US-Indexes with Mult-AI-Trading and Long strategies
6 Portfolio of US-Indexes with Mult-AI-Trading and Long strategies
Training, Validation and Test Periods for Backtest

In Order to backtest a trade strategy or portfolio that has AI models, the following data is required:

  1. Training Date Range

    1. Date range that will be used to train the AI models in the backtest
  2. Validation Date Range

    1. Date range that twill be used to validate the AI models, should not overlapped with the training date range
  3. Test Period Date Range

    1. This is the out-sample date range, which corresponds to the date range of the backtest

Date Ranges are defined with a DatasetDef object, and have the following parameters:

  1. strBegDateAIModels : Date to begin training or validation of an AI model
  2. strBegDate : Date to begin the backtest
  3. strEndDate : Date to end training, validation and Backtest

Note:

  1. The param strBegDateAIModels can be defined as the same date as strBegDate, that is the default, if not defined.
  2. The critical aspect of using this parameter is in the backtest. Some AI Models, such as time series, others using moving averages over many periods, create params with no predicting data for those initial dates. Thus, in order to ensure the backtest starts on the actual date specified, the strBegDateAIModels should be defined as an earlier date, and it should not overlapped with the validation period end-date to avoid any chance of bias by picking at the validation data.
In [132]:
training_period = DatasetDef(datasetType = DatasetType.Training,
                             strBegDateAIModels = "2001-07-01",
                             strBegDate         = "2002-01-01",
                             strEndDate         = "2006-12-31" )

validation_period = DatasetDef(datasetType = DatasetType.Validation,
                               strBegDateAIModels = "2006-07-01",
                               strBegDate         = "2007-01-01",
                               strEndDate         = "2008-06-30" )

testing_period = DatasetDef(datasetType = DatasetType.Testing,
                               strBegDateAIModels = "2008-07-01",
                               strBegDate         = "2009-01-01",
                               strEndDate         = "2009-12-31" )

fit_datasets = FitDatasetsDef( trainingDataset    = training_period,
                               validationDataset  = validation_period )
Execute Backtest
In [133]:
tsExecuteEngine = BacktestExecution( \
                    name = "Backtest for Portfolio of Multiple-AI-Modeled based Trade Strategies",
                    timePeriod  = testing_period,
                    fitDatasets = fit_datasets,
                    trade_asset_registered_item = portf_registered_obj )
In [ ]:
tsExecuteEngine.evaluate()
Backtest Metrics
Execution & Investment Metrics
In [135]:
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
        'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']]
Out[135]:
TA_Reg_Name Is_Portfolio Num_Trades_Completed Init_Capital Final_Capital Cum_Return Backtest_Status
0 Portfolio of US-Indexes with Mult-AI-Trading a... Yes 845 60000000.0 7.009235e+07 0.168206 Completed
1 ts_gru_1_^DJI No 72 2000000.0 2.410562e+06 0.205281 Completed
2 ts_lstm_^DJI No 42 2000000.0 2.510186e+06 0.255093 Completed
3 ts_conv1d_gru_^DJI No 50 2000000.0 2.232142e+06 0.116071 Completed
4 ts_conv1d_lstm_^DJI No 34 2000000.0 2.922561e+06 0.461280 Completed
5 ts_wavenet_^DJI No 40 2000000.0 2.267038e+06 0.133519 Completed
6 ts_wavenet_gru_^DJI No 38 2000000.0 2.400650e+06 0.200325 Completed
7 ts_wavenet_lstm_^DJI No 24 2000000.0 2.235235e+06 0.117617 Completed
8 ts_gru_2_^DJI No 82 2000000.0 2.572858e+06 0.286429 Completed
9 all_^DJI No 54 2000000.0 2.525422e+06 0.262711 Completed
10 ts_gru_1_^IXIC No 64 2000000.0 2.351447e+06 0.175723 Completed
11 ts_lstm_^IXIC No 40 2000000.0 1.834660e+06 -0.082670 Completed
12 ts_conv1d_gru_^IXIC No 46 2000000.0 1.857777e+06 -0.071112 Completed
13 ts_conv1d_lstm_^IXIC No 37 2000000.0 2.816539e+06 0.408269 Completed
14 ts_wavenet_^IXIC No 2 2000000.0 1.915524e+06 -0.042238 Completed
15 ts_wavenet_gru_^IXIC No 2 2000000.0 1.898595e+06 -0.050703 Completed
16 ts_wavenet_lstm_^IXIC No 2 2000000.0 1.940465e+06 -0.029767 Completed
17 ts_gru_2_^IXIC No 68 2000000.0 2.084553e+06 0.042277 Completed
18 all_^IXIC No 48 2000000.0 2.167578e+06 0.083789 Completed
19 ts_gru_1_^GSPC No 52 2000000.0 2.132592e+06 0.066296 Completed
20 ts_lstm_^GSPC No 11 2000000.0 2.446656e+06 0.223328 Completed
21 ts_conv1d_gru_^GSPC No 4 2000000.0 2.412789e+06 0.206395 Completed
22 ts_conv1d_lstm_^GSPC No 3 2000000.0 2.419068e+06 0.209534 Completed
23 ts_wavenet_^GSPC No 1 2000000.0 2.393362e+06 0.196681 Completed
24 ts_wavenet_gru_^GSPC No 1 2000000.0 2.393362e+06 0.196681 Completed
25 ts_wavenet_lstm_^GSPC No 3 2000000.0 2.541476e+06 0.270738 Completed
26 ts_gru_2_^GSPC No 20 2000000.0 2.562216e+06 0.281108 Completed
27 all_^GSPC No 2 2000000.0 2.365497e+06 0.182748 Completed
28 Long-Only Trade Strategy for ^GSPC No 1 2000000.0 2.393362e+06 0.196681 Completed
29 Long-Only Trade Strategy for ^IXIC No 1 2000000.0 2.780251e+06 0.390126 Completed
30 Long-Only Trade Strategy for ^DJI No 1 2000000.0 2.307932e+06 0.153966 Completed
Performance Metrics
In [136]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ]
Out[136]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
0 Portfolio of US-Indexes with Mult-AI-Trading a... Yes 2009-01-05 2009-12-31 1.0 0.17 0.17 0.95 -0.17 0.06 -0.04
1 ts_gru_1_^DJI No ts_gru_1 ^DJI 2009-01-05 2009-12-31 1.0 0.21 0.21 0.89 -0.18 0.07 -0.04
2 ts_lstm_^DJI No ts_lstm ^DJI 2009-01-05 2009-12-31 1.0 0.26 0.26 1.06 -0.18 0.07 -0.04
3 ts_conv1d_gru_^DJI No ts_conv1d_gru ^DJI 2009-01-05 2009-12-31 1.0 0.12 0.12 0.57 -0.2 0.07 -0.04
4 ts_conv1d_lstm_^DJI No ts_conv1d_lstm ^DJI 2009-01-05 2009-12-31 1.0 0.46 0.47 1.7 -0.17 0.07 -0.04
5 ts_wavenet_^DJI No ts_wavenet ^DJI 2009-01-05 2009-12-31 1.0 0.13 0.14 0.64 -0.21 0.07 -0.05
6 ts_wavenet_gru_^DJI No ts_wavenet_gru ^DJI 2009-01-05 2009-12-31 1.0 0.2 0.2 0.88 -0.17 0.07 -0.04
7 ts_wavenet_lstm_^DJI No ts_wavenet_lstm ^DJI 2009-01-05 2009-12-31 1.0 0.12 0.12 0.58 -0.17 0.07 -0.04
8 ts_gru_2_^DJI No ts_gru_2 ^DJI 2009-01-05 2009-12-31 1.0 0.29 0.29 1.16 -0.22 0.07 -0.04
9 all_^DJI No all ^DJI 2009-01-05 2009-12-31 0.97 0.26 0.27 1.1 -0.18 0.07 -0.04
10 ts_gru_1_^IXIC No ts_gru_1 ^IXIC 2009-01-05 2009-12-31 1.0 0.18 0.18 0.71 -0.25 0.07 -0.04
11 ts_lstm_^IXIC No ts_lstm ^IXIC 2009-01-05 2009-12-31 1.0 -0.08 -0.08 -0.15 -0.28 0.07 -0.08
12 ts_conv1d_gru_^IXIC No ts_conv1d_gru ^IXIC 2009-01-05 2009-12-31 1.0 -0.07 -0.07 -0.1 -0.3 0.07 -0.08
13 ts_conv1d_lstm_^IXIC No ts_conv1d_lstm ^IXIC 2009-01-05 2009-12-31 1.0 0.41 0.41 1.33 -0.21 0.07 -0.08
14 ts_wavenet_^IXIC No ts_wavenet ^IXIC 2009-01-05 2009-12-31 1.0 -0.04 -0.04 -0.0 -0.23 0.07 -0.06
15 ts_wavenet_gru_^IXIC No ts_wavenet_gru ^IXIC 2009-01-05 2009-12-31 1.0 -0.05 -0.05 -0.03 -0.23 0.07 -0.06
16 ts_wavenet_lstm_^IXIC No ts_wavenet_lstm ^IXIC 2009-01-05 2009-12-31 1.0 -0.03 -0.03 0.04 -0.23 0.07 -0.06
17 ts_gru_2_^IXIC No ts_gru_2 ^IXIC 2009-01-05 2009-12-31 1.0 0.04 0.04 0.29 -0.33 0.07 -0.04
18 all_^IXIC No all ^IXIC 2009-01-05 2009-12-31 0.97 0.08 0.09 0.43 -0.2 0.07 -0.06
19 ts_gru_1_^GSPC No ts_gru_1 ^GSPC 2009-01-05 2009-12-31 1.0 0.07 0.07 0.37 -0.19 0.07 -0.05
20 ts_lstm_^GSPC No ts_lstm ^GSPC 2009-01-05 2009-12-31 1.0 0.22 0.23 0.88 -0.26 0.07 -0.05
21 ts_conv1d_gru_^GSPC No ts_conv1d_gru ^GSPC 2009-01-05 2009-12-31 1.0 0.21 0.21 0.83 -0.26 0.07 -0.05
22 ts_conv1d_lstm_^GSPC No ts_conv1d_lstm ^GSPC 2009-01-05 2009-12-31 1.0 0.21 0.21 0.84 -0.28 0.07 -0.05
23 ts_wavenet_^GSPC No ts_wavenet ^GSPC 2009-01-05 2009-12-31 1.0 0.2 0.2 0.8 -0.28 0.07 -0.05
24 ts_wavenet_gru_^GSPC No ts_wavenet_gru ^GSPC 2009-01-05 2009-12-31 1.0 0.2 0.2 0.8 -0.28 0.07 -0.05
25 ts_wavenet_lstm_^GSPC No ts_wavenet_lstm ^GSPC 2009-01-05 2009-12-31 1.0 0.27 0.27 1.02 -0.26 0.07 -0.05
26 ts_gru_2_^GSPC No ts_gru_2 ^GSPC 2009-01-05 2009-12-31 1.0 0.28 0.29 1.05 -0.23 0.07 -0.05
27 all_^GSPC No all ^GSPC 2009-01-05 2009-12-31 0.99 0.18 0.19 0.76 -0.28 0.07 -0.05
28 Long-Only Trade Strategy for ^GSPC No long ^GSPC 2009-01-05 2009-12-31 1.0 0.2 0.2 0.8 -0.28 0.07 -0.05
29 Long-Only Trade Strategy for ^IXIC No long ^IXIC 2009-01-05 2009-12-31 1.0 0.39 0.4 1.32 -0.23 0.07 -0.06
30 Long-Only Trade Strategy for ^DJI No long ^DJI 2009-01-05 2009-12-31 1.0 0.15 0.16 0.72 -0.27 0.07 -0.05
In [137]:
tsExecuteEngine.getSummaryMetrics().T.head(60)
Out[137]:
0 1 2 3 4 5 6 7 8 9 ... 21 22 23 24 25 26 27 28 29 30
ta_reg_item_name Portfolio of US-Indexes with Mult-AI-Trading a... ts_gru_1_^DJI ts_lstm_^DJI ts_conv1d_gru_^DJI ts_conv1d_lstm_^DJI ts_wavenet_^DJI ts_wavenet_gru_^DJI ts_wavenet_lstm_^DJI ts_gru_2_^DJI all_^DJI ... ts_conv1d_gru_^GSPC ts_conv1d_lstm_^GSPC ts_wavenet_^GSPC ts_wavenet_gru_^GSPC ts_wavenet_lstm_^GSPC ts_gru_2_^GSPC all_^GSPC Long-Only Trade Strategy for ^GSPC Long-Only Trade Strategy for ^IXIC Long-Only Trade Strategy for ^DJI
ta_reg_item_id 6 94 95 96 97 98 99 100 101 102 ... 114 115 116 117 118 119 120 121 122 123
is_portfolio Yes No No No No No No No No No ... No No No No No No No No No No
model_type ts_gru_1 ts_lstm ts_conv1d_gru ts_conv1d_lstm ts_wavenet ts_wavenet_gru ts_wavenet_lstm ts_gru_2 all ... ts_conv1d_gru ts_conv1d_lstm ts_wavenet ts_wavenet_gru ts_wavenet_lstm ts_gru_2 all long long long
trade_asset ^DJI ^DJI ^DJI ^DJI ^DJI ^DJI ^DJI ^DJI ^DJI ... ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^IXIC ^DJI
test_period_len_days 364 364 364 364 364 364 364 364 364 364 ... 364 364 364 364 364 364 364 364 364 364
tr_period_len_days 1825 1825 1825 1825 1825 1825 1825 1825 1825 1825 ... 1825 1825 1825 1825 1825 1825 1825 1825 1825 1825
val_period_len_days 546 546 546 546 546 546 546 546 546 546 ... 546 546 546 546 546 546 546 546 546 546
index Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy ... Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy
Start Period 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 ... 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05
End Period 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 ... 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31
Risk-Free Rate 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
Time in Market 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.97 ... 1.0 1.0 1.0 1.0 1.0 1.0 0.99 1.0 1.0 1.0
Cumulative Return 0.17 0.21 0.26 0.12 0.46 0.13 0.2 0.12 0.29 0.26 ... 0.21 0.21 0.2 0.2 0.27 0.28 0.18 0.2 0.39 0.15
CAGR% 0.17 0.21 0.26 0.12 0.47 0.14 0.2 0.12 0.29 0.27 ... 0.21 0.21 0.2 0.2 0.27 0.29 0.19 0.2 0.4 0.16
Sharpe 0.95 0.89 1.06 0.57 1.7 0.64 0.88 0.58 1.16 1.1 ... 0.83 0.84 0.8 0.8 1.02 1.05 0.76 0.8 1.32 0.72
Sortino 1.48 1.36 1.64 0.87 2.76 0.96 1.34 0.88 1.82 1.7 ... 1.21 1.22 1.16 1.16 1.5 1.55 1.1 1.16 1.97 1.05
Sortino/√2 1.04 0.96 1.16 0.61 1.95 0.68 0.95 0.62 1.28 1.2 ... 0.86 0.86 0.82 0.82 1.06 1.1 0.77 0.82 1.39 0.74
Max Drawdown -0.17 -0.18 -0.18 -0.2 -0.17 -0.21 -0.17 -0.17 -0.22 -0.18 ... -0.26 -0.28 -0.28 -0.28 -0.26 -0.23 -0.28 -0.28 -0.23 -0.27
Longest DD Days 143 170 146 218 111 177 171 199 177 199 ... 117 145 145 145 117 93 145 145 92 197
Volatility (ann.) 0.18 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 ... 0.27 0.27 0.27 0.27 0.27 0.27 0.27 0.27 0.28 0.24
Calmar 1.01 1.14 1.48 0.59 2.68 0.65 1.16 0.68 1.33 1.52 ... 0.82 0.77 0.72 0.72 1.07 1.22 0.67 0.72 1.71 0.57
Skew 0.74 0.34 0.35 0.38 0.42 0.29 0.36 0.38 0.42 0.36 ... 0.07 0.03 0.04 0.04 0.04 0.06 0.05 0.04 0.09 0.17
Kurtosis 8.15 2.3 2.24 2.22 2.17 2.2 2.33 2.3 2.28 2.48 ... 2.07 2.08 2.07 2.07 2.08 2.07 2.09 2.07 1.77 2.41
Expected Daily % 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
Expected Monthly % 0.01 0.02 0.02 0.01 0.03 0.01 0.02 0.01 0.02 0.02 ... 0.02 0.02 0.02 0.02 0.02 0.02 0.01 0.02 0.03 0.01
Expected Yearly % 0.17 0.21 0.26 0.12 0.46 0.13 0.2 0.12 0.29 0.26 ... 0.21 0.21 0.2 0.2 0.27 0.28 0.18 0.2 0.39 0.15
Kelly Criterion 0.1 0.07 0.09 0.05 0.13 0.05 0.07 0.05 0.1 0.09 ... 0.08 0.08 0.07 0.07 0.09 0.09 0.07 0.07 0.12 0.06
Risk of Ruin 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
Daily Value-at-Risk -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 ... -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.02
Expected Shortfall (cVaR) -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 ... -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.02
Gain/Pain Ratio 0.24 0.17 0.2 0.1 0.34 0.12 0.17 0.11 0.23 0.22 ... 0.16 0.16 0.15 0.15 0.2 0.2 0.14 0.15 0.26 0.13
Gain/Pain (1M) 1.34 1.4 2.16 0.63 5.79 0.61 1.38 0.89 1.66 1.82 ... 1.18 0.93 0.88 0.88 1.5 1.46 0.83 0.88 1.91 0.71
Payoff Ratio 1.12 1.09 1.1 1.06 1.21 1.11 1.14 1.12 1.1 1.11 ... 0.93 0.92 0.93 0.93 0.95 1.0 0.93 0.93 0.97 0.97
Profit Factor 1.24 1.17 1.2 1.1 1.34 1.12 1.17 1.11 1.23 1.22 ... 1.16 1.16 1.15 1.15 1.2 1.2 1.14 1.15 1.26 1.13
Common Sense Ratio 1.34 1.15 1.34 1.19 1.75 1.14 1.23 1.23 1.27 1.38 ... 1.17 1.08 1.07 1.07 1.21 1.22 1.06 1.07 1.33 1.15
CPC Index 0.73 0.66 0.69 0.6 0.86 0.62 0.67 0.61 0.71 0.71 ... 0.6 0.59 0.59 0.59 0.63 0.66 0.58 0.59 0.69 0.59
Tail Ratio 1.08 0.99 1.11 1.08 1.3 1.02 1.06 1.11 1.04 1.14 ... 1.01 0.93 0.93 0.93 1.01 1.01 0.93 0.93 1.06 1.01
Outlier Win Ratio 5.85 3.69 3.5 3.58 3.36 3.2 3.57 3.49 3.82 3.74 ... 3.54 3.56 3.55 3.55 3.51 3.43 3.61 3.55 3.46 3.22
Outlier Loss Ratio 6.0 3.68 3.7 3.62 3.91 3.72 3.78 3.74 3.45 3.7 ... 3.61 3.58 3.6 3.6 3.64 3.75 3.58 3.6 3.13 3.65
MTD 0.02 0.04 0.04 0.06 0.07 0.02 0.02 0.02 0.01 0.07 ... 0.02 0.02 0.02 0.02 0.02 0.01 0.02 0.02 0.06 0.01
3M 0.03 0.08 0.1 0.11 0.09 0.09 0.03 -0.01 0.04 0.12 ... 0.05 0.06 0.05 0.05 0.05 0.03 0.05 0.05 0.07 0.07
6M 0.03 -0.01 0.04 0.07 0.08 -0.05 -0.04 -0.07 -0.1 0.05 ... 0.16 0.23 0.21 0.21 0.21 0.17 0.2 0.21 0.24 0.23
YTD 0.17 0.21 0.26 0.12 0.46 0.13 0.2 0.12 0.29 0.26 ... 0.21 0.21 0.2 0.2 0.27 0.28 0.18 0.2 0.39 0.15
1Y 0.17 0.21 0.26 0.12 0.46 0.13 0.2 0.12 0.29 0.26 ... 0.21 0.21 0.2 0.2 0.27 0.28 0.18 0.2 0.39 0.15
3Y (ann.) 0.17 0.21 0.26 0.12 0.47 0.14 0.2 0.12 0.29 0.27 ... 0.21 0.21 0.2 0.2 0.27 0.29 0.19 0.2 0.4 0.16
5Y (ann.) 0.17 0.21 0.26 0.12 0.47 0.14 0.2 0.12 0.29 0.27 ... 0.21 0.21 0.2 0.2 0.27 0.29 0.19 0.2 0.4 0.16
10Y (ann.) 0.17 0.21 0.26 0.12 0.47 0.14 0.2 0.12 0.29 0.27 ... 0.21 0.21 0.2 0.2 0.27 0.29 0.19 0.2 0.4 0.16
All-time (ann.) 0.17 0.21 0.26 0.12 0.47 0.14 0.2 0.12 0.29 0.27 ... 0.21 0.21 0.2 0.2 0.27 0.29 0.19 0.2 0.4 0.16
Best Day 0.06 0.07 0.07 0.07 0.07 0.07 0.07 0.07 0.07 0.07 ... 0.07 0.07 0.07 0.07 0.07 0.07 0.07 0.07 0.07 0.07
Worst Day -0.04 -0.04 -0.04 -0.04 -0.04 -0.05 -0.04 -0.04 -0.04 -0.04 ... -0.05 -0.05 -0.05 -0.05 -0.05 -0.05 -0.05 -0.05 -0.06 -0.05
Best Month 0.12 0.25 0.12 0.22 0.15 0.08 0.13 0.08 0.17 0.12 ... 0.09 0.09 0.09 0.09 0.09 0.13 0.09 0.09 0.12 0.09
Worst Month -0.07 -0.06 -0.07 -0.08 -0.05 -0.12 -0.08 -0.11 -0.09 -0.08 ... -0.11 -0.11 -0.11 -0.11 -0.11 -0.11 -0.12 -0.11 -0.1 -0.12
Best Year 0.17 0.21 0.26 0.12 0.46 0.13 0.2 0.12 0.29 0.26 ... 0.21 0.21 0.2 0.2 0.27 0.28 0.18 0.2 0.39 0.15
Worst Year 0.17 0.21 0.26 0.12 0.46 0.13 0.2 0.12 0.29 0.26 ... 0.21 0.21 0.2 0.2 0.27 0.28 0.18 0.2 0.39 0.15
Avg. Drawdown -0.02 -0.05 -0.04 -0.09 -0.03 -0.06 -0.04 -0.04 -0.05 -0.05 ... -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.03
Avg. Drawdown Days 16 28 24 59 16 33 18 22 22 24 ... 14 15 15 15 13 14 15 15 12 15
Recovery Factor 0.99 1.12 1.45 0.58 2.64 0.64 1.15 0.67 1.31 1.5 ... 0.81 0.76 0.71 0.71 1.06 1.2 0.66 0.71 1.68 0.56
Ulcer Index 1.2 1.04 1.04 1.05 1.03 1.04 1.04 1.04 1.03 1.04 ... 1.06 1.26 1.26 1.26 1.05 1.43 inf 1.26 1.11 1.21
Avg. Up Month 0.04 0.06 0.05 0.05 0.05 0.04 0.04 0.04 0.08 0.05 ... 0.04 0.05 0.05 0.05 0.05 0.06 0.05 0.05 0.06 0.05

60 rows × 31 columns

Persist Backtest to DB (optional )
In [28]:
session.add( tsExecuteEngine )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst)
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")
 done

Portfolio G

  1. Portfolio G: Combines all Trade Strategies in Portfolio E and F

    Description:

     1. Portfolio with 63 trading strategies
     2. $200,000/strategy, Total Budget = $12.6M
     3. No-Rebalance during the backtest 
     4. 100% capital invested
     5. Portfolio investment using equal weights for each trade strategy
    
    

    Trade Strategies:

     1. Three trade strategies: Nasdaq, S&P 500, and DOW Jones with buy-and-hold
    
     2. Fifty-Seven trade strategies, 19 trade strategies per US Index, as defined in
        Portfolio E and F
    
     3. Three trade strategies: Nasdaq, S&P 500, and DOW Jones using the following Composite 
        model configuration: 
    
         - A Composite Trade Strategy based on all the Trading Models configured above per US Index
    
         - The Set Entry cofiguration rules are: 
           a. Majority Voting (default)
           b. Enter a trade if the last n voting decisions are the same, set to 1 (default )
           c. Enter a trade if there is cross-over signaled after applying rules a) and b), 
              set to False (default)
    
         - The Set Exit configuration rules are: 
           a. Majority Voting (Default)
               - Exit a long trade if the percent of Trading Models signaled an exit for a long position
                  is greater that the percent signaling no-exit 
               - Exit a short trade if the percent of Trading Models signaled an exit for a short position
                  is greater that the percent signaling no-exit 
           b. Exit a trade if the last n exit decisions are the same, set to 1 (default )

Backtest:

1. Type: regular

2. AI Models Fit Date Ranges
    1. Training Period: 
        1. Begin Date = 2001-01-01 
        2. End Date   = 2006-12-31  
    2. Validation Period: 
        1. Begin Date = 2007-01-01 
        2. End Date   = 2008-12-31 

3. Test Period: 
    1. Begin Date = 2009-01-01 
    2. End Date   = 2009-12-31         
Portfolio Trade Assets
In [138]:
portfolio_trade_assets   = [ "^DJI", "^IXIC", "^GSPC" ]
Market Data Manager
In [139]:
dirPathMarketData = '/Users/gustavozambrana/Google Drive/Python/Projects/Trade_Engine/Data/US_Market_Indixes'

supportedTradeAssets   = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str           = "2000-01-01"
end_date_str           = None

ts_marketdat_mng = TradeStrategyMarketDataMng(\
        marketDataProviderName = "yahoofinance",
        supportedTradeAssets   = supportedTradeAssets,
        stock_price_col_name   = "Adj Close",
        fileNameMarketData     = "US_Indixes_And_ETFs_MrkData",
        dirPathMarketData      = dirPathMarketData,
        beg_date_str           = beg_date_str,
        end_date_str           = end_date_str,
        interval               = "1d"  ) 
2021-10-28 19:05:17,293 [INFO] root: Found previous Market data previously loaded to specified file and dir.
Pipeline Data Manager
In [140]:
ts_model_pipline_mng_g = TradeStrategyModelPipelineDataMng(\
                            tsMarketDataMng    = ts_marketdat_mng,
                            package            = "trade_engine.model.ai.WaveNet_RNN_AI_PipelineBuilder",
                            model_class_name   = "WaveNet_RNN_AI_PipelineBuilder",
                            fileNameMarketData = "WaveNet_RNN_AI_Pipeline_Data_Portf_G",
                            forceCreatePipelineData = True,
                            dirPathMarketData  = dirPathMarketData )
Simulation Broker
In [141]:
brokerTradingObj = SimBrokerTrading()
Trade Strategies, Trade Investment Manager, and Trade Asset Register Items
In [143]:
tsConfDat = TradeStrategyConfigData()

# Set Config

tsConfDat.tsSetConfig(\
    ts_set_conf_dict = 
           { 'set_actions_conf' : 
                      { "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
                        "exit"  : { 'votingPolicy' : 1, 
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1 } 
                      }
           } )
           
# TS #1

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_gru_1", 
    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "gru",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'         : 20 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 1, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },

                               "stop_lost" :
                                    { 'model'    : "fix_perc",
                                      'type'     : "ta",
                                      'obj_args' : { 'long_stop_los_per' : 5, 'short_stop_los_per'    : 5 }  } 
                             },
                    }  )

# TS #2

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_lstm", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'         : 50,   'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn'   : True,
                                                 'epochs'          : 20 }  
                                }
                            } }  )
# TS #3
    
tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_conv1d_gru", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "conv1d_gru",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'   : 50,   'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'          : 20 }  
                                }
                            } }  )

# TS #4

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_conv1d_lstm", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "conv1d_lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'  : 50,   'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'          : 20 }  
                                }
                            } }  )

# TS #5

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_wavenet", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "wavenet",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'      : 50,   'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'          : 20 }  
                                }
                            } }  )

# TS #6

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_wavenet_gru", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "wavenet_gru",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'      : 50,   'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'          : 20 }  
                                }
                            } }  )

# TS #7
tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_wavenet_lstm", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "wavenet_lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'      : 50,   'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'          : 20 }  
                                }
                            } }  )

# TS #8
tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_gru_2", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "gru",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'          : 40,   'no_neurons_lay1'    : 20,
                                         'no_neurons_lay2' : 20,   'pred_ahead_periods' : 3,
                                         'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                         'epochs'          : 20 }  
                                }
                            } }  )

# TS #9

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_1",    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 10, 'win_slow' : 50 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 },
                                },
                            }  } )
# TS #10

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_2",    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 15, 'win_slow' : 60 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 },
                                },
                            }  } )
# TS #11

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_bb",    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "bb",
                                  'type'     : "ta",
                                  'obj_args' : { 'window' : 13, 'window_dev' : 1 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 },
                                },
                            }  } )
# TS #12

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_macd",    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "macd",
                                  'type'     : "ta",
                                  'obj_args' : { 'window_slow' : 26, 'window_fast' : 12, 'window_sign' : 9,
                                                 'enter_long_macd_diff'  : 0.5 , 'exi_long_macd_diff' : 0.5,
                                                 'enter_short_macd_diff' : -0.5, 'exi_short_macd_diff' : -0.5  },
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 },
                                },
                            }  } )
# TS #13

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_rsi",    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "rsi",
                                  'type'     : "ta",
                                  'obj_args' : { 'rsi_enter_long'  : 30.0,  'rsi_exit_long'  : 30.0, 
                                                 'rsi_enter_short' : 70.0,  'rsi_exit_short' : 70.0 },
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 },
                                },
                            }  } )
# TS #14

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_srsi",    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "srsi",
                                  'type'     : "ta",
                                  'obj_args' : { 'window' : 14,  'smooth1' : 3, 'smooth2'  : 3,
                                                 'srsi_enter_long'  : 0.8,  'srsi_exit_long'  : 0.8,
                                                 'srsi_enter_short' : 0.2,  'srsi_exit_short' : 0.2 },
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 },
                                },
                            }  } )
# TS #15

tsConfDat.addTSConf(\
   ts_conf_dict = { 
      'ts_unique_tag' : "ts_adx",    
      'actions_conf'  : { "entry_exit" :  
                            { 'model'    : "adx",
                              'type'     : "ta",
                              'obj_args' : { 'window' : 14, 'adx_enter_long_ge' : 14, 'adx_exit_long_lt'  : 14,
                                             'adx_enter_short_ge' : 14, 'adx_exit_short_lt' : 14 },
                              'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                              'exit_policy_args'   : { 'lastn_match' : 1 },
                            },
                        }  } )
# TS #16

tsConfDat.addTSConf(\
   ts_conf_dict = { 
      'ts_unique_tag' : "ts_kama",    
      'actions_conf'  : { "entry_exit" :  
                            { 'model'    : "kama",
                              'type'     : "ta",
                              'obj_args' : { 'window_fast' : 10, 'pow1_fast' : 2, 'pow2_fast'  : 30,
                                             'window_slow' : 10, 'pow1_slow' : 5, 'pow2_slow'  : 30 },
                              'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                              'exit_policy_args'   : { 'lastn_match' : 1 },
                            },
                        }  } )
# TS #17

tsConfDat.addTSConf(\
   ts_conf_dict = { 
      'ts_unique_tag' : "ts_tsi",    
      'actions_conf'  : { "entry_exit" :  
                            { 'model'    : "tsi",
                              'type'     : "ta",
                              'obj_args' : { 'window_slow' : 25, 'window_fast' : 5 },
                              'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                              'exit_policy_args'   : { 'lastn_match' : 1 },
                            },
                        }  } )

# TS #118

tsConfDat.addTSConf(\
   ts_conf_dict = { 
      'ts_unique_tag' : "ts_forceindex",    
      'actions_conf'  : { "entry_exit" :  
                            { 'model'    : "forceindex",
                              'type'     : "ta",
                              'obj_args' : { 'window' : 39 },
                              'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                              'exit_policy_args'   : { 'lastn_match' : 1 },
                            },
                        }  } )

# TS #19

tsConfDat.addTSConf(\
   ts_conf_dict = { 
      'ts_unique_tag' : "ts_mfi",    
      'actions_conf'  : { "entry_exit" :  
                            { 'model'    : "mfi",
                              'type'     : "ta",
                              'obj_args' : { 'window' : 14, 'long_slope_win' : 15, 'short_slope_win' : 15 },
                              'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                              'exit_policy_args'   : { 'lastn_match' : 1 },
                            },
                        }  } )
In [ ]:
taRegisterItems = [ ]
tsActionGen = TradeStrategyActionGenerator()

for trade_asset in portfolio_trade_assets :
    
    num_ts = len(tsConfDat.name_list) + 1  # adding the composite  trade strategy
    
    for i in range( num_ts ) :

        if i <= num_ts - 2:
            # *** Trade Strategy 

            actionDatItem  = tsConfDat.getTSConfigDataForItem(item_num = i )
            ts_unique_name = actionDatItem.name_list[0]
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = actionDatItem,
                                                     pipelineMng       = ts_model_pipline_mng_g )
        else :
            # Composite Trade Strategy 
            
            ts_unique_name = "all"            
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = tsConfDat,
                                                     pipelineMng       = ts_model_pipline_mng_g )

        ts_model = TradeStrategyBaseModelPersist(\
                        trade_asset               = trade_asset,
                        ts_marketdat_mng          = ts_marketdat_mng,
                        ts_enter                  = trade_enter_set,
                        ts_exit                   = trade_exit_set,                       
                        model_type                = ts_unique_name,
                        model_version             = "1.0",
                        market_data_period        = MarketDataPeriod.Day,
                    ) 

        # *** Trade Strategy Investment Manager 

        taInvMng = TradingAssetInvMngBase(\
                                        trade_asset                = trade_asset,
                                        minPeriodsBetweenTrades    = 1,
                                        initInvestment             = 1000000.0, 
                                        capPercentToInvestPerTrade = 100.0,
                                        minInvestPercent           = 5.0,
                                        min_account_balance        = 1000.0 )

        # *** Trade Register Item
        # *** This object has all configuration defined to execute a given trade strategy,
        # *** It can be executed individually in backtest or as part of a portfolio

        ta_registered_item = TradingAssetRegisterItem(\
                trade_name                    = "{0}_{1}".format(ts_unique_name, trade_asset), 
                ts_model                      = ts_model,
                tradingExecutionType          = TradingAssetExecutionType.Simulation,
                tradingBrokerObj              = brokerTradingObj,
                tradingAssetInvMngObj         = taInvMng )  

        taRegisterItems.append(ta_registered_item)
In [145]:
print("Number of configured Trade Asset Register Items: ", len(taRegisterItems) )
Number of configured Trade Asset Register Items:  60
Portfolio Investment Manager
In [146]:
# *** Porttfolio Investment Manager across all individual trade strategies investment managers
# *** Role: 
# ***    1) Managed investment funds across n number of trade strategies
# ***    2) Rebalance portfolio periodically or never
# ***    3) Portfolio Policy Weights 
# ***          equal weights (default)
# ***          MinimumVariance
# ***          User defined 
# ***    4) Track Portfolio level returns and metrics
# ***          Individual Trade Strategies return and metrics tracked through their 
# ***          investment managers
# ***          Portfolio funds are split across each trade strategy investment manager based on the
# ***          portfolio weights

portfInvMng = PortfolioInvMng(\
                  name                       = "Portfolio Inv. Manager for US-Indexes - TechAnal & AI Trading Models TS",
                  initInvestment             = 2000000.0 * ( len(taRegisterItems) + 3),  # 200K/trade-strag
                  portfRebalanceFreq         = PortfolioRebalanceFrequency.Never,
                  portfRebalancePeriods      = 1,
                  minInvestPercent           = 5.0,
                  min_account_balance        = 1000.0,     
                  minPeriodsBetweenTrades    = 1,
                  capPercentToInvestPerTrade = 100.0 )
Trade Register Items Portfolio
In [147]:
# *** Set of Trade Register Items
#
# Configuration Summary:
#    - Each set has 1 to n trade register items as previously described 
#    - Optionally add long only trade strategies for all unique trade assets in the
#      portfolio 
#           - (Dow, Nasdaq, and S&P 500 for this portfolio) in this example
#           - Might be useful for bench marking trade strategies
#    - Each set has one Investment Portfolio Manager
#       - portfolio funds allocated per portfolio policy rules and re-balanced (if defined), 
#         across all trade strategies


portf_registered_obj = PortfolioRegisterItem(\
                        name                 = "Portfolio G, US-Indexes with TechAnal & AI Trading Models, and Long strategies",
                        taRegisterItems      = taRegisterItems,
                        portfolioInvMngObj   = portfInvMng,
                        tradingExecutionType = TradingAssetExecutionType.Simulation,
                        add_long_only_ts     = True )
2021-10-28 19:06:34,488 [INFO] root: *** Adding long only trade strategies for : {'^GSPC', '^IXIC', '^DJI'}
Persist to DB (optional)
In [ ]:
session.add( portf_registered_obj )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")
Re-Store from DB (optional)
In [ ]:
session.expunge_all()
del portf_registered_obj

for tsObj in session.query(PortfolioRegisterItem):  
    print(tsObj.name)
    if  tsObj.name  == "Portfolio G, US-Indexes with TechAnal & AI Trading Models, and Long strategies" :
        break

portf_registered_obj = tsObj
print(portf_registered_obj.id, portf_registered_obj.name)
Training, Validation and Test Periods for Backtest

In Order to backtest a trade strategy or portfolio that has AI models, the following data is required:

  1. Training Date Range

    1. Date range that will be used to train the AI models in the backtest
  2. Validation Date Range

    1. Date range that twill be used to validate the AI models, should not overlapped with the training date range
  3. Test Period Date Range

    1. This is the out-sample date range, which corresponds to the date range of the backtest

Date Ranges are defined with a DatasetDef object, and have the following parameters:

  1. strBegDateAIModels : Date to begin training or validation of an AI model
  2. strBegDate : Date to begin the backtest
  3. strEndDate : Date to end training, validation and Backtest

Note:

  1. The param strBegDateAIModels can be defined as the same date as strBegDate, that is the default, if not defined.
  2. The critical aspect of using this parameter is in the backtest. Some AI Models, such as time series, others using moving averages over many periods, create params with no predicting data for those initial dates. Thus, in order to ensure the backtest starts on the actual date specified, the strBegDateAIModels should be defined as an earlier date, and it should not overlapped with the validation period end-date to avoid any chance of bias by picking at the validation data.
In [148]:
training_period = DatasetDef(datasetType = DatasetType.Training,
                             strBegDateAIModels = "2000-07-01",
                             strBegDate         = "2001-01-01",
                             strEndDate         = "2006-12-31" )

validation_period = DatasetDef(datasetType = DatasetType.Validation,
                               strBegDateAIModels = "2006-07-01",
                               strBegDate         = "2007-01-01",
                               strEndDate         = "2008-12-31" )

testing_period = DatasetDef(datasetType = DatasetType.Testing,
                               strBegDateAIModels = "2008-07-01",
                               strBegDate         = "2009-01-01",
                               strEndDate         = "2009-12-31" )

fit_datasets = FitDatasetsDef( trainingDataset    = training_period,
                               validationDataset  = validation_period )
Execute Backtest
In [149]:
tsExecuteEngine = BacktestExecution( \
                    name = "Backtest for Portfolio G",
                    timePeriod  = testing_period,
                    fitDatasets = fit_datasets,
                    trade_asset_registered_item = portf_registered_obj )
In [ ]:
tsExecuteEngine.evaluate()
Backtest Metrics
Trade Strategies Execution & Investment Metrics

DOW Jones

In [157]:
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
        'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
        query('TA_Reg_Name.str.contains("DJI")', engine='python')
Out[157]:
TA_Reg_Name Is_Portfolio Num_Trades_Completed Init_Capital Final_Capital Cum_Return Backtest_Status
1 ts_gru_1_^DJI No 74 2000000.0 2.522902e+06 0.261451 Completed
2 ts_lstm_^DJI No 42 2000000.0 2.490160e+06 0.245080 Completed
3 ts_conv1d_gru_^DJI No 54 2000000.0 2.246321e+06 0.123160 Completed
4 ts_conv1d_lstm_^DJI No 36 2000000.0 2.384650e+06 0.192325 Completed
5 ts_wavenet_^DJI No 39 2000000.0 2.317959e+06 0.158980 Completed
6 ts_wavenet_gru_^DJI No 49 2000000.0 2.489064e+06 0.244532 Completed
7 ts_wavenet_lstm_^DJI No 41 2000000.0 2.545570e+06 0.272785 Completed
8 ts_gru_2_^DJI No 86 2000000.0 2.409593e+06 0.204797 Completed
9 ts_sma_1_^DJI No 6 2000000.0 2.368059e+06 0.184029 Completed
10 ts_sma_2_^DJI No 4 2000000.0 2.454280e+06 0.227140 Completed
11 ts_bb_^DJI No 46 2000000.0 1.880761e+06 -0.059619 Completed
12 ts_macd_^DJI No 21 2000000.0 1.808427e+06 -0.095786 Completed
13 ts_rsi_^DJI No 11 2000000.0 2.163856e+06 0.081928 Completed
14 ts_srsi_^DJI No 39 2000000.0 2.060352e+06 0.030176 Completed
15 ts_adx_^DJI No 22 2000000.0 2.145482e+06 0.072741 Completed
16 ts_kama_^DJI No 3 2000000.0 2.653478e+06 0.326739 Completed
17 ts_tsi_^DJI No 7 2000000.0 2.550770e+06 0.275385 Completed
18 ts_forceindex_^DJI No 14 2000000.0 2.318384e+06 0.159192 Completed
19 ts_mfi_^DJI No 32 2000000.0 1.724867e+06 -0.137567 Completed
20 all_^DJI No 76 2000000.0 2.389533e+06 0.194766 Completed
63 Long-Only Trade Strategy for ^DJI No 1 2000000.0 2.307932e+06 0.153966 Completed

Nasdaq

In [158]:
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
        'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
        query('TA_Reg_Name.str.contains("IXIC")', engine='python')
Out[158]:
TA_Reg_Name Is_Portfolio Num_Trades_Completed Init_Capital Final_Capital Cum_Return Backtest_Status
21 ts_gru_1_^IXIC No 74 2000000.0 2.527445e+06 0.263723 Completed
22 ts_lstm_^IXIC No 44 2000000.0 2.277402e+06 0.138701 Completed
23 ts_conv1d_gru_^IXIC No 50 2000000.0 2.358985e+06 0.179492 Completed
24 ts_conv1d_lstm_^IXIC No 36 2000000.0 2.212704e+06 0.106352 Completed
25 ts_wavenet_^IXIC No 2 2000000.0 1.898595e+06 -0.050703 Completed
26 ts_wavenet_gru_^IXIC No 2 2000000.0 1.940465e+06 -0.029767 Completed
27 ts_wavenet_lstm_^IXIC No 2 2000000.0 1.898595e+06 -0.050703 Completed
28 ts_gru_2_^IXIC No 72 2000000.0 2.806475e+06 0.403238 Completed
29 ts_sma_1_^IXIC No 7 2000000.0 2.125976e+06 0.062988 Completed
30 ts_sma_2_^IXIC No 6 2000000.0 2.530324e+06 0.265162 Completed
31 ts_bb_^IXIC No 40 2000000.0 2.086084e+06 0.043042 Completed
32 ts_macd_^IXIC No 30 2000000.0 1.772608e+06 -0.113696 Completed
33 ts_rsi_^IXIC No 4 2000000.0 1.823801e+06 -0.088100 Completed
34 ts_srsi_^IXIC No 46 2000000.0 1.845952e+06 -0.077024 Completed
35 ts_adx_^IXIC No 18 2000000.0 2.099621e+06 0.049811 Completed
36 ts_kama_^IXIC No 3 2000000.0 2.621990e+06 0.310995 Completed
37 ts_tsi_^IXIC No 10 2000000.0 1.897423e+06 -0.051289 Completed
38 ts_forceindex_^IXIC No 15 2000000.0 2.131114e+06 0.065557 Completed
39 ts_mfi_^IXIC No 36 2000000.0 1.808008e+06 -0.095996 Completed
40 all_^IXIC No 80 2000000.0 1.992194e+06 -0.003903 Completed
62 Long-Only Trade Strategy for ^IXIC No 1 2000000.0 2.780251e+06 0.390126 Completed

S&P 500

In [159]:
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
        'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
        query('TA_Reg_Name.str.contains("GSPC")', engine='python')
Out[159]:
TA_Reg_Name Is_Portfolio Num_Trades_Completed Init_Capital Final_Capital Cum_Return Backtest_Status
41 ts_gru_1_^GSPC No 22 2000000.0 2.695396e+06 0.347698 Completed
42 ts_lstm_^GSPC No 4 2000000.0 2.410210e+06 0.205105 Completed
43 ts_conv1d_gru_^GSPC No 2 2000000.0 2.526111e+06 0.263055 Completed
44 ts_conv1d_lstm_^GSPC No 1 2000000.0 2.393362e+06 0.196681 Completed
45 ts_wavenet_^GSPC No 1 2000000.0 2.393362e+06 0.196681 Completed
46 ts_wavenet_gru_^GSPC No 1 2000000.0 2.393362e+06 0.196681 Completed
47 ts_wavenet_lstm_^GSPC No 1 2000000.0 2.393362e+06 0.196681 Completed
48 ts_gru_2_^GSPC No 32 2000000.0 2.621147e+06 0.310574 Completed
49 ts_sma_1_^GSPC No 7 2000000.0 2.129982e+06 0.064991 Completed
50 ts_sma_2_^GSPC No 7 2000000.0 2.504244e+06 0.252122 Completed
51 ts_bb_^GSPC No 36 2000000.0 2.091174e+06 0.045587 Completed
52 ts_macd_^GSPC No 34 2000000.0 1.572109e+06 -0.213945 Completed
53 ts_rsi_^GSPC No 12 2000000.0 2.203553e+06 0.101777 Completed
54 ts_srsi_^GSPC No 41 2000000.0 1.769603e+06 -0.115198 Completed
55 ts_adx_^GSPC No 23 2000000.0 2.162504e+06 0.081252 Completed
56 ts_kama_^GSPC No 2 2000000.0 2.532568e+06 0.266284 Completed
57 ts_tsi_^GSPC No 10 2000000.0 2.153106e+06 0.076553 Completed
58 ts_forceindex_^GSPC No 15 2000000.0 2.053591e+06 0.026795 Completed
59 ts_mfi_^GSPC No 35 2000000.0 1.776214e+06 -0.111893 Completed
60 all_^GSPC No 27 2000000.0 2.639818e+06 0.319909 Completed
61 Long-Only Trade Strategy for ^GSPC No 1 2000000.0 2.393362e+06 0.196681 Completed
Performance Metrics

Dow Jones

In [160]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
        query('trade_asset == "^DJI" ')
Out[160]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
1 ts_gru_1_^DJI No ts_gru_1 ^DJI 2009-01-05 2009-12-31 1.0 0.26 0.27 1.09 -0.2 0.07 -0.04
2 ts_lstm_^DJI No ts_lstm ^DJI 2009-01-05 2009-12-31 1.0 0.25 0.25 1.03 -0.18 0.07 -0.04
3 ts_conv1d_gru_^DJI No ts_conv1d_gru ^DJI 2009-01-05 2009-12-31 1.0 0.12 0.12 0.6 -0.2 0.07 -0.04
4 ts_conv1d_lstm_^DJI No ts_conv1d_lstm ^DJI 2009-01-05 2009-12-31 1.0 0.19 0.2 0.85 -0.18 0.06 -0.07
5 ts_wavenet_^DJI No ts_wavenet ^DJI 2009-01-05 2009-12-31 1.0 0.16 0.16 0.73 -0.22 0.07 -0.04
6 ts_wavenet_gru_^DJI No ts_wavenet_gru ^DJI 2009-01-05 2009-12-31 1.0 0.24 0.25 1.03 -0.21 0.07 -0.05
7 ts_wavenet_lstm_^DJI No ts_wavenet_lstm ^DJI 2009-01-05 2009-12-31 1.0 0.27 0.28 1.12 -0.21 0.07 -0.05
8 ts_gru_2_^DJI No ts_gru_2 ^DJI 2009-01-05 2009-12-31 1.0 0.2 0.21 0.89 -0.19 0.07 -0.04
9 ts_sma_1_^DJI No ts_sma_1 ^DJI 2009-01-05 2009-12-31 0.99 0.18 0.19 0.87 -0.15 0.05 -0.06
10 ts_sma_2_^DJI No ts_sma_2 ^DJI 2009-01-05 2009-12-31 0.99 0.23 0.23 1.11 -0.17 0.04 -0.05
11 ts_bb_^DJI No ts_bb ^DJI 2009-01-05 2009-12-31 0.71 -0.06 -0.06 -0.18 -0.22 0.06 -0.07
12 ts_macd_^DJI No ts_macd ^DJI 2009-01-05 2009-12-31 0.93 -0.1 -0.1 -0.34 -0.23 0.07 -0.05
13 ts_rsi_^DJI No ts_rsi ^DJI 2009-01-05 2009-12-31 0.09 0.08 0.08 0.96 -0.03 0.06 -0.03
14 ts_srsi_^DJI No ts_srsi ^DJI 2009-01-05 2009-12-31 0.47 0.03 0.03 0.26 -0.15 0.07 -0.05
15 ts_adx_^DJI No ts_adx ^DJI 2009-01-05 2009-12-31 0.89 0.07 0.07 0.46 -0.21 0.04 -0.04
16 ts_kama_^DJI No ts_kama ^DJI 2009-01-05 2009-12-31 1.0 0.33 0.33 1.52 -0.19 0.04 -0.05
17 ts_tsi_^DJI No ts_tsi ^DJI 2009-01-05 2009-12-31 0.98 0.28 0.28 1.21 -0.11 0.07 -0.04
18 ts_forceindex_^DJI No ts_forceindex ^DJI 2009-01-05 2009-12-31 0.94 0.16 0.16 0.8 -0.13 0.04 -0.05
19 ts_mfi_^DJI No ts_mfi ^DJI 2009-01-05 2009-12-31 0.54 -0.14 -0.14 -0.8 -0.27 0.04 -0.04
20 all_^DJI No all ^DJI 2009-01-05 2009-12-31 0.95 0.19 0.2 0.88 -0.12 0.07 -0.04
63 Long-Only Trade Strategy for ^DJI No long ^DJI 2009-01-05 2009-12-31 1.0 0.15 0.16 0.72 -0.27 0.07 -0.05
In [161]:
tsExecuteEngine.getSummaryMetrics().query('trade_asset == "^DJI" ').T.head(60)
Out[161]:
1 2 3 4 5 6 7 8 9 10 ... 12 13 14 15 16 17 18 19 20 63
ta_reg_item_name ts_gru_1_^DJI ts_lstm_^DJI ts_conv1d_gru_^DJI ts_conv1d_lstm_^DJI ts_wavenet_^DJI ts_wavenet_gru_^DJI ts_wavenet_lstm_^DJI ts_gru_2_^DJI ts_sma_1_^DJI ts_sma_2_^DJI ... ts_macd_^DJI ts_rsi_^DJI ts_srsi_^DJI ts_adx_^DJI ts_kama_^DJI ts_tsi_^DJI ts_forceindex_^DJI ts_mfi_^DJI all_^DJI Long-Only Trade Strategy for ^DJI
ta_reg_item_id None None None None None None None None None None ... None None None None None None None None None None
is_portfolio No No No No No No No No No No ... No No No No No No No No No No
model_type ts_gru_1 ts_lstm ts_conv1d_gru ts_conv1d_lstm ts_wavenet ts_wavenet_gru ts_wavenet_lstm ts_gru_2 ts_sma_1 ts_sma_2 ... ts_macd ts_rsi ts_srsi ts_adx ts_kama ts_tsi ts_forceindex ts_mfi all long
trade_asset ^DJI ^DJI ^DJI ^DJI ^DJI ^DJI ^DJI ^DJI ^DJI ^DJI ... ^DJI ^DJI ^DJI ^DJI ^DJI ^DJI ^DJI ^DJI ^DJI ^DJI
test_period_len_days 364 364 364 364 364 364 364 364 364 364 ... 364 364 364 364 364 364 364 364 364 364
tr_period_len_days 2190 2190 2190 2190 2190 2190 2190 2190 2190 2190 ... 2190 2190 2190 2190 2190 2190 2190 2190 2190 2190
val_period_len_days 730 730 730 730 730 730 730 730 730 730 ... 730 730 730 730 730 730 730 730 730 730
index Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy ... Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy
Start Period 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 ... 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05
End Period 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 ... 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31
Risk-Free Rate 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
Time in Market 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.99 0.99 ... 0.93 0.09 0.47 0.89 1.0 0.98 0.94 0.54 0.95 1.0
Cumulative Return 0.26 0.25 0.12 0.19 0.16 0.24 0.27 0.2 0.18 0.23 ... -0.1 0.08 0.03 0.07 0.33 0.28 0.16 -0.14 0.19 0.15
CAGR% 0.27 0.25 0.12 0.2 0.16 0.25 0.28 0.21 0.19 0.23 ... -0.1 0.08 0.03 0.07 0.33 0.28 0.16 -0.14 0.2 0.16
Sharpe 1.09 1.03 0.6 0.85 0.73 1.03 1.12 0.89 0.87 1.11 ... -0.34 0.96 0.26 0.46 1.52 1.21 0.8 -0.8 0.88 0.72
Sortino 1.67 1.6 0.9 1.23 1.15 1.57 1.71 1.36 1.25 1.62 ... -0.5 2.06 0.39 0.65 2.29 1.87 1.15 -1.09 1.4 1.05
Sortino/√2 1.18 1.13 0.64 0.87 0.82 1.11 1.21 0.96 0.88 1.15 ... -0.35 1.45 0.28 0.46 1.62 1.32 0.81 -0.77 0.99 0.74
Max Drawdown -0.2 -0.18 -0.2 -0.18 -0.22 -0.21 -0.21 -0.19 -0.15 -0.17 ... -0.23 -0.03 -0.15 -0.21 -0.19 -0.11 -0.13 -0.27 -0.12 -0.27
Longest DD Days 182 210 213 169 177 177 147 177 147 296 ... 255 150 279 296 219 92 99 294 177 197
Volatility (ann.) 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.22 0.2 ... 0.22 0.09 0.17 0.2 0.2 0.22 0.21 0.17 0.23 0.24
Calmar 1.36 1.42 0.62 1.11 0.72 1.19 1.33 1.1 1.27 1.38 ... -0.42 2.5 0.2 0.35 1.78 2.64 1.23 -0.52 1.66 0.57
Skew 0.37 0.4 0.37 -0.25 0.6 0.29 0.23 0.38 -0.26 -0.19 ... 0.38 5.64 0.78 -0.02 -0.1 0.41 -0.19 0.07 0.64 0.17
Kurtosis 2.33 2.27 2.24 2.21 2.19 2.25 2.35 2.34 1.67 0.9 ... 2.68 67.83 10.28 1.09 0.81 2.13 1.04 3.07 2.92 2.41
Expected Daily % 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... -0.0 0.0 0.0 0.0 0.0 0.0 0.0 -0.0 0.0 0.0
Expected Monthly % 0.02 0.02 0.01 0.01 0.01 0.02 0.02 0.02 0.01 0.02 ... -0.01 0.01 0.0 0.01 0.02 0.02 0.01 -0.01 0.01 0.01
Expected Yearly % 0.26 0.25 0.12 0.19 0.16 0.24 0.27 0.2 0.18 0.23 ... -0.1 0.08 0.03 0.07 0.33 0.28 0.16 -0.14 0.19 0.15
Kelly Criterion 0.09 0.08 0.05 0.07 0.06 0.08 0.09 0.08 0.08 0.09 ... -0.03 0.28 0.03 0.04 0.13 0.1 0.07 -0.09 0.07 0.06
Risk of Ruin 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
Daily Value-at-Risk -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 ... -0.02 -0.01 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02
Expected Shortfall (cVaR) -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 ... -0.02 -0.01 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02
Gain/Pain Ratio 0.21 0.2 0.11 0.16 0.14 0.2 0.22 0.17 0.16 0.21 ... -0.06 0.97 0.07 0.09 0.29 0.23 0.15 -0.16 0.17 0.13
Gain/Pain (1M) 1.22 1.15 0.55 1.7 0.86 0.84 1.28 1.48 1.13 1.36 ... -0.32 2.78 0.35 0.41 2.62 5.12 1.28 -0.37 2.58 0.71
Payoff Ratio 1.09 1.19 1.1 1.1 1.16 1.13 1.13 1.07 1.0 0.99 ... 1.08 1.48 1.15 0.92 1.01 1.07 0.96 0.96 1.21 0.97
Profit Factor 1.21 1.2 1.11 1.16 1.14 1.2 1.22 1.17 1.16 1.21 ... 0.94 1.97 1.07 1.09 1.29 1.23 1.15 0.84 1.17 1.13
Common Sense Ratio 1.26 1.34 1.19 1.29 1.41 1.39 1.33 1.17 1.11 1.33 ... 0.98 NaN 0.95 1.16 1.44 1.44 1.28 0.63 1.38 1.15
CPC Index 0.69 0.71 0.61 0.65 0.65 0.7 0.71 0.65 0.63 0.66 ... 0.47 1.67 0.59 0.54 0.73 0.71 0.6 0.37 0.7 0.59
Tail Ratio 1.04 1.12 1.07 1.11 1.24 1.16 1.09 1.0 0.96 1.1 ... 1.05 NaN 0.89 1.07 1.12 1.17 1.11 0.76 1.18 1.01
Outlier Win Ratio 3.87 3.42 3.51 3.0 3.65 3.2 3.22 3.89 3.24 3.19 ... 3.77 23.99 10.39 4.09 3.12 3.44 3.61 8.17 4.31 3.22
Outlier Loss Ratio 3.49 3.87 3.69 3.83 3.38 3.79 3.83 3.46 3.39 3.35 ... 3.32 1.3 3.03 3.03 2.83 3.15 3.22 2.54 3.49 3.65
MTD 0.04 0.04 0.02 0.04 0.02 0.04 0.04 -0.0 0.01 0.01 ... -0.02 0.0 -0.03 -0.04 0.01 0.01 0.01 -0.03 0.02 0.01
3M 0.09 0.01 0.08 0.06 -0.05 0.07 0.08 0.02 0.07 0.07 ... -0.06 0.0 -0.02 -0.03 0.07 0.02 -0.02 -0.11 0.04 0.07
6M -0.05 0.02 -0.03 0.01 -0.18 -0.09 0.04 -0.08 0.07 0.01 ... -0.12 -0.0 -0.03 0.06 0.23 0.1 0.12 -0.12 -0.02 0.23
YTD 0.26 0.25 0.12 0.19 0.16 0.24 0.27 0.2 0.18 0.23 ... -0.1 0.08 0.03 0.07 0.33 0.28 0.16 -0.14 0.19 0.15
1Y 0.26 0.25 0.12 0.19 0.16 0.24 0.27 0.2 0.18 0.23 ... -0.1 0.08 0.03 0.07 0.33 0.28 0.16 -0.14 0.19 0.15
3Y (ann.) 0.27 0.25 0.12 0.2 0.16 0.25 0.28 0.21 0.19 0.23 ... -0.1 0.08 0.03 0.07 0.33 0.28 0.16 -0.14 0.2 0.16
5Y (ann.) 0.27 0.25 0.12 0.2 0.16 0.25 0.28 0.21 0.19 0.23 ... -0.1 0.08 0.03 0.07 0.33 0.28 0.16 -0.14 0.2 0.16
10Y (ann.) 0.27 0.25 0.12 0.2 0.16 0.25 0.28 0.21 0.19 0.23 ... -0.1 0.08 0.03 0.07 0.33 0.28 0.16 -0.14 0.2 0.16
All-time (ann.) 0.27 0.25 0.12 0.2 0.16 0.25 0.28 0.21 0.19 0.23 ... -0.1 0.08 0.03 0.07 0.33 0.28 0.16 -0.14 0.2 0.16
Best Day 0.07 0.07 0.07 0.06 0.07 0.07 0.07 0.07 0.05 0.04 ... 0.07 0.06 0.07 0.04 0.04 0.07 0.04 0.04 0.07 0.07
Worst Day -0.04 -0.04 -0.04 -0.07 -0.04 -0.05 -0.05 -0.04 -0.06 -0.05 ... -0.05 -0.03 -0.05 -0.04 -0.05 -0.04 -0.05 -0.04 -0.04 -0.05
Best Month 0.15 0.15 0.26 0.1 0.12 0.2 0.09 0.1 0.12 0.11 ... 0.08 0.11 0.06 0.1 0.11 0.11 0.07 0.09 0.09 0.09
Worst Month -0.1 -0.08 -0.11 -0.07 -0.11 -0.11 -0.11 -0.05 -0.06 -0.11 ... -0.05 -0.02 -0.06 -0.07 -0.05 -0.03 -0.07 -0.08 -0.05 -0.12
Best Year 0.26 0.25 0.12 0.19 0.16 0.24 0.27 0.2 0.18 0.23 ... -0.1 0.08 0.03 0.07 0.33 0.28 0.16 -0.14 0.19 0.15
Worst Year 0.26 0.25 0.12 0.19 0.16 0.24 0.27 0.2 0.18 0.23 ... -0.1 0.08 0.03 0.07 0.33 0.28 0.16 -0.14 0.19 0.15
Avg. Drawdown -0.05 -0.03 -0.05 -0.06 -0.04 -0.04 -0.05 -0.05 -0.03 -0.03 ... -0.05 -0.02 -0.04 -0.04 -0.02 -0.02 -0.03 -0.06 -0.04 -0.03
Avg. Drawdown Days 30 31 25 38 15 21 23 33 18 33 ... 30 76 43 34 16 15 17 55 17 15
Recovery Factor 1.34 1.39 0.61 1.1 0.71 1.18 1.3 1.08 1.25 1.36 ... -0.42 2.47 0.2 0.34 1.75 2.6 1.21 -0.51 1.63 0.56
Ulcer Index 1.03 1.04 1.04 1.04 1.03 1.03 1.04 1.03 1.13 1.04 ... 1.11 inf 1.01 1.07 1.03 1.09 1.1 1.05 1.03 1.21
Avg. Up Month 0.08 0.06 0.06 0.04 0.05 0.08 0.05 0.07 0.05 0.04 ... 0.04 0.04 0.02 0.04 0.05 0.04 0.03 0.06 0.05 0.05

60 rows × 21 columns

Nasdaq

In [162]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
        query('trade_asset == "^IXIC" ')
Out[162]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
21 ts_gru_1_^IXIC No ts_gru_1 ^IXIC 2009-01-05 2009-12-31 1.0 0.26 0.27 0.96 -0.21 0.07 -0.04
22 ts_lstm_^IXIC No ts_lstm ^IXIC 2009-01-05 2009-12-31 1.0 0.14 0.14 0.6 -0.23 0.07 -0.06
23 ts_conv1d_gru_^IXIC No ts_conv1d_gru ^IXIC 2009-01-05 2009-12-31 1.0 0.18 0.18 0.72 -0.21 0.07 -0.06
24 ts_conv1d_lstm_^IXIC No ts_conv1d_lstm ^IXIC 2009-01-05 2009-12-31 1.0 0.11 0.11 0.49 -0.25 0.07 -0.08
25 ts_wavenet_^IXIC No ts_wavenet ^IXIC 2009-01-05 2009-12-31 1.0 -0.05 -0.05 -0.03 -0.23 0.07 -0.06
26 ts_wavenet_gru_^IXIC No ts_wavenet_gru ^IXIC 2009-01-05 2009-12-31 1.0 -0.03 -0.03 0.04 -0.23 0.07 -0.06
27 ts_wavenet_lstm_^IXIC No ts_wavenet_lstm ^IXIC 2009-01-05 2009-12-31 1.0 -0.05 -0.05 -0.03 -0.23 0.07 -0.06
28 ts_gru_2_^IXIC No ts_gru_2 ^IXIC 2009-01-05 2009-12-31 1.0 0.4 0.41 1.33 -0.25 0.07 -0.04
29 ts_sma_1_^IXIC No ts_sma_1 ^IXIC 2009-01-05 2009-12-31 0.98 0.06 0.06 0.36 -0.23 0.05 -0.07
30 ts_sma_2_^IXIC No ts_sma_2 ^IXIC 2009-01-05 2009-12-31 0.99 0.27 0.27 0.99 -0.21 0.05 -0.07
31 ts_bb_^IXIC No ts_bb ^IXIC 2009-01-05 2009-12-31 0.67 0.04 0.04 0.3 -0.17 0.07 -0.07
32 ts_macd_^IXIC No ts_macd ^IXIC 2009-01-05 2009-12-31 0.89 -0.11 -0.12 -0.33 -0.15 0.07 -0.05
33 ts_rsi_^IXIC No ts_rsi ^IXIC 2009-01-05 2009-12-31 0.07 -0.09 -0.09 -1.19 -0.1 0.01 -0.07
34 ts_srsi_^IXIC No ts_srsi ^IXIC 2009-01-05 2009-12-31 0.54 -0.08 -0.08 -0.25 -0.22 0.07 -0.07
35 ts_adx_^IXIC No ts_adx ^IXIC 2009-01-05 2009-12-31 0.9 0.05 0.05 0.32 -0.14 0.07 -0.05
36 ts_kama_^IXIC No ts_kama ^IXIC 2009-01-05 2009-12-31 1.0 0.31 0.32 1.2 -0.21 0.05 -0.05
37 ts_tsi_^IXIC No ts_tsi ^IXIC 2009-01-05 2009-12-31 0.97 -0.05 -0.05 -0.06 -0.23 0.07 -0.05
38 ts_forceindex_^IXIC No ts_forceindex ^IXIC 2009-01-05 2009-12-31 0.94 0.07 0.07 0.37 -0.21 0.07 -0.05
39 ts_mfi_^IXIC No ts_mfi ^IXIC 2009-01-05 2009-12-31 0.52 -0.1 -0.1 -0.4 -0.16 0.06 -0.07
40 all_^IXIC No all ^IXIC 2009-01-05 2009-12-31 0.96 -0.0 -0.0 0.13 -0.22 0.07 -0.07
62 Long-Only Trade Strategy for ^IXIC No long ^IXIC 2009-01-05 2009-12-31 1.0 0.39 0.4 1.32 -0.23 0.07 -0.06
In [163]:
tsExecuteEngine.getSummaryMetrics().query('trade_asset == "^IXIC" ').T.head(60)
Out[163]:
21 22 23 24 25 26 27 28 29 30 ... 32 33 34 35 36 37 38 39 40 62
ta_reg_item_name ts_gru_1_^IXIC ts_lstm_^IXIC ts_conv1d_gru_^IXIC ts_conv1d_lstm_^IXIC ts_wavenet_^IXIC ts_wavenet_gru_^IXIC ts_wavenet_lstm_^IXIC ts_gru_2_^IXIC ts_sma_1_^IXIC ts_sma_2_^IXIC ... ts_macd_^IXIC ts_rsi_^IXIC ts_srsi_^IXIC ts_adx_^IXIC ts_kama_^IXIC ts_tsi_^IXIC ts_forceindex_^IXIC ts_mfi_^IXIC all_^IXIC Long-Only Trade Strategy for ^IXIC
ta_reg_item_id None None None None None None None None None None ... None None None None None None None None None None
is_portfolio No No No No No No No No No No ... No No No No No No No No No No
model_type ts_gru_1 ts_lstm ts_conv1d_gru ts_conv1d_lstm ts_wavenet ts_wavenet_gru ts_wavenet_lstm ts_gru_2 ts_sma_1 ts_sma_2 ... ts_macd ts_rsi ts_srsi ts_adx ts_kama ts_tsi ts_forceindex ts_mfi all long
trade_asset ^IXIC ^IXIC ^IXIC ^IXIC ^IXIC ^IXIC ^IXIC ^IXIC ^IXIC ^IXIC ... ^IXIC ^IXIC ^IXIC ^IXIC ^IXIC ^IXIC ^IXIC ^IXIC ^IXIC ^IXIC
test_period_len_days 364 364 364 364 364 364 364 364 364 364 ... 364 364 364 364 364 364 364 364 364 364
tr_period_len_days 2190 2190 2190 2190 2190 2190 2190 2190 2190 2190 ... 2190 2190 2190 2190 2190 2190 2190 2190 2190 2190
val_period_len_days 730 730 730 730 730 730 730 730 730 730 ... 730 730 730 730 730 730 730 730 730 730
index Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy ... Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy
Start Period 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 ... 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05
End Period 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 ... 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31
Risk-Free Rate 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
Time in Market 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.98 0.99 ... 0.89 0.07 0.54 0.9 1.0 0.97 0.94 0.52 0.96 1.0
Cumulative Return 0.26 0.14 0.18 0.11 -0.05 -0.03 -0.05 0.4 0.06 0.27 ... -0.11 -0.09 -0.08 0.05 0.31 -0.05 0.07 -0.1 -0.0 0.39
CAGR% 0.27 0.14 0.18 0.11 -0.05 -0.03 -0.05 0.41 0.06 0.27 ... -0.12 -0.09 -0.08 0.05 0.32 -0.05 0.07 -0.1 -0.0 0.4
Sharpe 0.96 0.6 0.72 0.49 -0.03 0.04 -0.03 1.33 0.36 0.99 ... -0.33 -1.19 -0.25 0.32 1.2 -0.06 0.37 -0.4 0.13 1.32
Sortino 1.52 0.89 1.07 0.71 -0.05 0.06 -0.05 2.15 0.49 1.37 ... -0.47 -1.21 -0.37 0.46 1.76 -0.08 0.54 -0.54 0.18 1.97
Sortino/√2 1.08 0.63 0.76 0.5 -0.03 0.04 -0.03 1.52 0.35 0.97 ... -0.33 -0.86 -0.26 0.33 1.25 -0.06 0.38 -0.38 0.13 1.39
Max Drawdown -0.21 -0.23 -0.21 -0.25 -0.23 -0.23 -0.23 -0.25 -0.23 -0.21 ... -0.15 -0.1 -0.22 -0.14 -0.21 -0.23 -0.21 -0.16 -0.22 -0.23
Longest DD Days 217 216 178 168 163 161 163 217 197 183 ... 231 296 279 202 190 358 132 245 132 92
Volatility (ann.) 0.29 0.29 0.29 0.29 0.29 0.29 0.29 0.29 0.27 0.28 ... 0.27 0.08 0.22 0.26 0.25 0.27 0.26 0.2 0.28 0.28
Calmar 1.28 0.61 0.88 0.43 -0.22 -0.13 -0.22 1.64 0.28 1.31 ... -0.76 -0.92 -0.35 0.35 1.48 -0.23 0.32 -0.62 -0.02 1.71
Skew 0.51 0.2 0.18 -0.18 0.34 0.33 0.34 0.5 -0.48 -0.54 ... 0.33 -13.36 0.48 0.21 -0.16 0.02 0.14 -0.26 -0.03 0.09
Kurtosis 1.57 1.67 1.61 2.04 1.33 1.37 1.33 1.46 1.64 1.65 ... 1.99 197.45 6.16 1.61 0.81 1.55 1.74 6.06 2.04 1.77
Expected Daily % 0.0 0.0 0.0 0.0 -0.0 -0.0 -0.0 0.0 0.0 0.0 ... -0.0 -0.0 -0.0 0.0 0.0 -0.0 0.0 -0.0 -0.0 0.0
Expected Monthly % 0.02 0.01 0.01 0.01 -0.0 -0.0 -0.0 0.03 0.01 0.02 ... -0.01 -0.01 -0.01 0.0 0.02 -0.0 0.01 -0.01 -0.0 0.03
Expected Yearly % 0.26 0.14 0.18 0.11 -0.05 -0.03 -0.05 0.4 0.06 0.27 ... -0.11 -0.09 -0.08 0.05 0.31 -0.05 0.07 -0.1 -0.0 0.39
Kelly Criterion 0.08 0.05 0.06 0.04 -0.0 0.0 -0.0 0.1 0.04 0.09 ... -0.03 -1.11 -0.03 0.03 0.1 -0.01 0.03 -0.05 0.01 0.12
Risk of Ruin 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
Daily Value-at-Risk -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 ... -0.03 -0.01 -0.02 -0.03 -0.03 -0.03 -0.03 -0.02 -0.03 -0.03
Expected Shortfall (cVaR) -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 ... -0.03 -0.01 -0.02 -0.03 -0.03 -0.03 -0.03 -0.02 -0.03 -0.03
Gain/Pain Ratio 0.18 0.11 0.13 0.09 -0.01 0.01 -0.01 0.26 0.07 0.19 ... -0.06 -0.75 -0.06 0.06 0.23 -0.01 0.07 -0.09 0.02 0.26
Gain/Pain (1M) 1.13 0.61 0.94 0.53 -0.03 0.03 -0.03 1.72 0.3 1.46 ... -0.34 -0.99 -0.22 0.41 1.71 -0.05 0.4 -0.3 0.12 1.91
Payoff Ratio 1.17 1.17 1.2 1.14 1.07 1.05 1.07 1.23 0.82 0.87 ... 1.06 0.42 1.09 1.04 1.0 0.89 0.97 0.96 0.99 0.97
Profit Factor 1.18 1.11 1.13 1.09 0.99 1.01 0.99 1.26 1.07 1.19 ... 0.94 0.25 0.94 1.06 1.23 0.99 1.07 0.91 1.02 1.26
Common Sense Ratio 1.36 1.08 1.17 1.18 1.17 1.17 1.17 1.51 0.97 1.22 ... 0.99 NaN 0.92 1.11 1.25 0.85 1.09 0.83 1.04 1.33
CPC Index 0.7 0.63 0.66 0.61 0.51 0.52 0.51 0.78 0.49 0.6 ... 0.47 0.04 0.48 0.56 0.68 0.46 0.54 0.42 0.51 0.69
Tail Ratio 1.15 0.98 1.03 1.09 1.17 1.16 1.17 1.2 0.91 1.03 ... 1.05 NaN 0.97 1.04 1.02 0.86 1.02 0.91 1.02 1.06
Outlier Win Ratio 3.71 3.22 3.16 3.04 3.11 3.16 3.11 3.6 3.47 3.26 ... 3.85 31.12 8.4 3.87 3.23 3.47 3.52 8.59 3.71 3.46
Outlier Loss Ratio 3.22 3.42 3.44 3.7 3.1 3.09 3.1 3.27 3.34 3.56 ... 3.35 0.76 2.84 3.05 3.09 3.1 3.24 3.12 3.38 3.13
MTD -0.01 0.01 0.03 0.02 -0.07 -0.07 -0.07 0.0 0.06 0.06 ... -0.04 0.0 -0.04 -0.03 0.06 0.06 0.06 0.02 0.01 0.06
3M 0.03 -0.08 0.04 -0.06 -0.09 -0.08 -0.09 0.04 -0.03 0.07 ... -0.05 0.0 -0.05 -0.1 0.07 -0.0 -0.05 0.01 -0.1 0.07
6M -0.13 -0.16 -0.06 -0.07 -0.16 -0.14 -0.16 -0.16 0.12 0.24 ... -0.05 -0.01 -0.09 -0.05 0.24 -0.0 0.04 -0.03 -0.08 0.24
YTD 0.26 0.14 0.18 0.11 -0.05 -0.03 -0.05 0.4 0.06 0.27 ... -0.11 -0.09 -0.08 0.05 0.31 -0.05 0.07 -0.1 -0.0 0.39
1Y 0.26 0.14 0.18 0.11 -0.05 -0.03 -0.05 0.4 0.06 0.27 ... -0.11 -0.09 -0.08 0.05 0.31 -0.05 0.07 -0.1 -0.0 0.39
3Y (ann.) 0.27 0.14 0.18 0.11 -0.05 -0.03 -0.05 0.41 0.06 0.27 ... -0.12 -0.09 -0.08 0.05 0.32 -0.05 0.07 -0.1 -0.0 0.4
5Y (ann.) 0.27 0.14 0.18 0.11 -0.05 -0.03 -0.05 0.41 0.06 0.27 ... -0.12 -0.09 -0.08 0.05 0.32 -0.05 0.07 -0.1 -0.0 0.4
10Y (ann.) 0.27 0.14 0.18 0.11 -0.05 -0.03 -0.05 0.41 0.06 0.27 ... -0.12 -0.09 -0.08 0.05 0.32 -0.05 0.07 -0.1 -0.0 0.4
All-time (ann.) 0.27 0.14 0.18 0.11 -0.05 -0.03 -0.05 0.41 0.06 0.27 ... -0.12 -0.09 -0.08 0.05 0.32 -0.05 0.07 -0.1 -0.0 0.4
Best Day 0.07 0.07 0.07 0.07 0.07 0.07 0.07 0.07 0.05 0.05 ... 0.07 0.01 0.07 0.07 0.05 0.07 0.07 0.06 0.07 0.07
Worst Day -0.04 -0.06 -0.06 -0.08 -0.06 -0.06 -0.06 -0.04 -0.07 -0.07 ... -0.05 -0.07 -0.07 -0.05 -0.05 -0.05 -0.05 -0.07 -0.07 -0.06
Best Month 0.19 0.34 0.28 0.27 0.12 0.12 0.12 0.15 0.12 0.11 ... 0.04 0.0 0.1 0.11 0.1 0.12 0.12 0.12 0.12 0.12
Worst Month -0.11 -0.09 -0.09 -0.08 -0.1 -0.1 -0.1 -0.13 -0.13 -0.1 ... -0.06 -0.08 -0.06 -0.04 -0.08 -0.09 -0.08 -0.07 -0.13 -0.1
Best Year 0.26 0.14 0.18 0.11 -0.05 -0.03 -0.05 0.4 0.06 0.27 ... -0.11 -0.09 -0.08 0.05 0.31 -0.05 0.07 -0.1 -0.0 0.39
Worst Year 0.26 0.14 0.18 0.11 -0.05 -0.03 -0.05 0.4 0.06 0.27 ... -0.11 -0.09 -0.08 0.05 0.31 -0.05 0.07 -0.1 -0.0 0.39
Avg. Drawdown -0.05 -0.06 -0.06 -0.08 -0.06 -0.06 -0.06 -0.05 -0.04 -0.03 ... -0.09 -0.1 -0.07 -0.05 -0.04 -0.23 -0.04 -0.12 -0.06 -0.03
Avg. Drawdown Days 27 30 37 37 33 32 33 23 28 17 ... 87 296 48 34 20 358 22 119 25 12
Recovery Factor 1.26 0.6 0.87 0.43 -0.22 -0.13 -0.22 1.61 0.28 1.29 ... -0.75 -0.91 -0.35 0.34 1.46 -0.23 0.32 -0.61 -0.02 1.68
Ulcer Index 1.11 1.13 1.13 1.13 1.13 1.13 1.13 1.1 1.42 1.13 ... 1.08 inf inf 1.05 1.11 1.09 1.06 1.05 1.45 1.11
Avg. Up Month 0.09 0.08 0.07 0.09 0.06 0.06 0.06 0.09 0.05 0.05 ... 0.04 0.0 0.06 0.06 0.05 0.06 0.05 0.04 0.05 0.06

60 rows × 21 columns

S&P 500

In [164]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
        query('trade_asset == "^GSPC" ')
Out[164]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
41 ts_gru_1_^GSPC No ts_gru_1 ^GSPC 2009-01-05 2009-12-31 1.0 0.35 0.35 1.24 -0.22 0.07 -0.05
42 ts_lstm_^GSPC No ts_lstm ^GSPC 2009-01-05 2009-12-31 1.0 0.21 0.21 0.83 -0.26 0.07 -0.05
43 ts_conv1d_gru_^GSPC No ts_conv1d_gru ^GSPC 2009-01-05 2009-12-31 1.0 0.26 0.27 1.0 -0.26 0.07 -0.05
44 ts_conv1d_lstm_^GSPC No ts_conv1d_lstm ^GSPC 2009-01-05 2009-12-31 1.0 0.2 0.2 0.8 -0.28 0.07 -0.05
45 ts_wavenet_^GSPC No ts_wavenet ^GSPC 2009-01-05 2009-12-31 1.0 0.2 0.2 0.8 -0.28 0.07 -0.05
46 ts_wavenet_gru_^GSPC No ts_wavenet_gru ^GSPC 2009-01-05 2009-12-31 1.0 0.2 0.2 0.8 -0.28 0.07 -0.05
47 ts_wavenet_lstm_^GSPC No ts_wavenet_lstm ^GSPC 2009-01-05 2009-12-31 1.0 0.2 0.2 0.8 -0.28 0.07 -0.05
48 ts_gru_2_^GSPC No ts_gru_2 ^GSPC 2009-01-05 2009-12-31 1.0 0.31 0.32 1.14 -0.22 0.07 -0.05
49 ts_sma_1_^GSPC No ts_sma_1 ^GSPC 2009-01-05 2009-12-31 0.98 0.06 0.07 0.38 -0.17 0.05 -0.06
50 ts_sma_2_^GSPC No ts_sma_2 ^GSPC 2009-01-05 2009-12-31 0.98 0.25 0.26 1.03 -0.19 0.05 -0.06
51 ts_bb_^GSPC No ts_bb ^GSPC 2009-01-05 2009-12-31 0.67 0.05 0.05 0.31 -0.18 0.06 -0.07
52 ts_macd_^GSPC No ts_macd ^GSPC 2009-01-05 2009-12-31 0.87 -0.21 -0.22 -0.85 -0.27 0.07 -0.05
53 ts_rsi_^GSPC No ts_rsi ^GSPC 2009-01-05 2009-12-31 0.08 0.1 0.1 1.08 -0.04 0.06 -0.04
54 ts_srsi_^GSPC No ts_srsi ^GSPC 2009-01-05 2009-12-31 0.47 -0.12 -0.12 -0.53 -0.2 0.07 -0.06
55 ts_adx_^GSPC No ts_adx ^GSPC 2009-01-05 2009-12-31 0.91 0.08 0.08 0.44 -0.17 0.07 -0.04
56 ts_kama_^GSPC No ts_kama ^GSPC 2009-01-05 2009-12-31 1.0 0.27 0.27 1.15 -0.22 0.04 -0.05
57 ts_tsi_^GSPC No ts_tsi ^GSPC 2009-01-05 2009-12-31 0.97 0.08 0.08 0.42 -0.15 0.07 -0.04
58 ts_forceindex_^GSPC No ts_forceindex ^GSPC 2009-01-05 2009-12-31 0.93 0.03 0.03 0.23 -0.17 0.05 -0.05
59 ts_mfi_^GSPC No ts_mfi ^GSPC 2009-01-05 2009-12-31 0.44 -0.11 -0.11 -0.54 -0.18 0.05 -0.06
60 all_^GSPC No all ^GSPC 2009-01-05 2009-12-31 0.98 0.32 0.33 1.18 -0.2 0.07 -0.05
61 Long-Only Trade Strategy for ^GSPC No long ^GSPC 2009-01-05 2009-12-31 1.0 0.2 0.2 0.8 -0.28 0.07 -0.05
In [165]:
tsExecuteEngine.getSummaryMetrics().query('trade_asset == "^GSPC" ').T.head(60)
Out[165]:
41 42 43 44 45 46 47 48 49 50 ... 52 53 54 55 56 57 58 59 60 61
ta_reg_item_name ts_gru_1_^GSPC ts_lstm_^GSPC ts_conv1d_gru_^GSPC ts_conv1d_lstm_^GSPC ts_wavenet_^GSPC ts_wavenet_gru_^GSPC ts_wavenet_lstm_^GSPC ts_gru_2_^GSPC ts_sma_1_^GSPC ts_sma_2_^GSPC ... ts_macd_^GSPC ts_rsi_^GSPC ts_srsi_^GSPC ts_adx_^GSPC ts_kama_^GSPC ts_tsi_^GSPC ts_forceindex_^GSPC ts_mfi_^GSPC all_^GSPC Long-Only Trade Strategy for ^GSPC
ta_reg_item_id None None None None None None None None None None ... None None None None None None None None None None
is_portfolio No No No No No No No No No No ... No No No No No No No No No No
model_type ts_gru_1 ts_lstm ts_conv1d_gru ts_conv1d_lstm ts_wavenet ts_wavenet_gru ts_wavenet_lstm ts_gru_2 ts_sma_1 ts_sma_2 ... ts_macd ts_rsi ts_srsi ts_adx ts_kama ts_tsi ts_forceindex ts_mfi all long
trade_asset ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ... ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC
test_period_len_days 364 364 364 364 364 364 364 364 364 364 ... 364 364 364 364 364 364 364 364 364 364
tr_period_len_days 2190 2190 2190 2190 2190 2190 2190 2190 2190 2190 ... 2190 2190 2190 2190 2190 2190 2190 2190 2190 2190
val_period_len_days 730 730 730 730 730 730 730 730 730 730 ... 730 730 730 730 730 730 730 730 730 730
index Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy ... Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy
Start Period 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 ... 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05 2009-01-05
End Period 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 ... 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31 2009-12-31
Risk-Free Rate 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
Time in Market 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.98 0.98 ... 0.87 0.08 0.47 0.91 1.0 0.97 0.93 0.44 0.98 1.0
Cumulative Return 0.35 0.21 0.26 0.2 0.2 0.2 0.2 0.31 0.06 0.25 ... -0.21 0.1 -0.12 0.08 0.27 0.08 0.03 -0.11 0.32 0.2
CAGR% 0.35 0.21 0.27 0.2 0.2 0.2 0.2 0.32 0.07 0.26 ... -0.22 0.1 -0.12 0.08 0.27 0.08 0.03 -0.11 0.33 0.2
Sharpe 1.24 0.83 1.0 0.8 0.8 0.8 0.8 1.14 0.38 1.03 ... -0.85 1.08 -0.53 0.44 1.15 0.42 0.23 -0.54 1.18 0.8
Sortino 1.86 1.21 1.47 1.16 1.16 1.16 1.16 1.69 0.52 1.47 ... -1.21 2.28 -0.76 0.67 1.7 0.62 0.32 -0.72 1.76 1.16
Sortino/√2 1.31 0.85 1.04 0.82 0.82 0.82 0.82 1.19 0.37 1.04 ... -0.85 1.61 -0.54 0.48 1.2 0.44 0.23 -0.51 1.25 0.82
Max Drawdown -0.22 -0.26 -0.26 -0.28 -0.28 -0.28 -0.28 -0.22 -0.17 -0.19 ... -0.27 -0.04 -0.2 -0.17 -0.22 -0.15 -0.17 -0.18 -0.2 -0.28
Longest DD Days 59 117 117 145 145 145 145 100 122 218 ... 255 140 279 296 289 199 131 344 92 145
Volatility (ann.) 0.27 0.27 0.27 0.27 0.27 0.27 0.27 0.27 0.25 0.25 ... 0.25 0.09 0.2 0.24 0.23 0.25 0.24 0.19 0.27 0.27
Calmar 1.58 0.81 1.04 0.72 0.72 0.72 0.72 1.44 0.38 1.38 ... -0.81 2.58 -0.59 0.49 1.25 0.53 0.16 -0.65 1.64 0.72
Skew 0.07 0.07 0.04 0.04 0.04 0.04 0.04 0.06 -0.36 -0.29 ... 0.42 5.3 0.6 0.47 -0.06 0.3 -0.12 -0.34 0.09 0.04
Kurtosis 2.07 2.07 2.08 2.07 2.07 2.07 2.07 2.08 1.6 1.57 ... 2.49 71.25 8.65 2.0 0.76 1.99 1.21 6.44 2.34 2.07
Expected Daily % 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... -0.0 0.0 -0.0 0.0 0.0 0.0 0.0 -0.0 0.0 0.0
Expected Monthly % 0.03 0.02 0.02 0.02 0.02 0.02 0.02 0.02 0.01 0.02 ... -0.02 0.01 -0.01 0.01 0.02 0.01 0.0 -0.01 0.02 0.02
Expected Yearly % 0.35 0.21 0.26 0.2 0.2 0.2 0.2 0.31 0.06 0.25 ... -0.21 0.1 -0.12 0.08 0.27 0.08 0.03 -0.11 0.32 0.2
Kelly Criterion 0.11 0.07 0.09 0.07 0.07 0.07 0.07 0.1 0.04 0.09 ... -0.08 0.33 -0.06 0.04 0.09 0.04 0.02 -0.07 0.1 0.07
Risk of Ruin 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
Daily Value-at-Risk -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.02 ... -0.03 -0.01 -0.02 -0.02 -0.02 -0.03 -0.02 -0.02 -0.03 -0.03
Expected Shortfall (cVaR) -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.02 ... -0.03 -0.01 -0.02 -0.02 -0.02 -0.03 -0.02 -0.02 -0.03 -0.03
Gain/Pain Ratio 0.24 0.16 0.19 0.15 0.15 0.15 0.15 0.22 0.07 0.2 ... -0.15 1.3 -0.13 0.08 0.21 0.08 0.04 -0.13 0.24 0.15
Gain/Pain (1M) 2.49 1.17 1.42 0.88 0.88 0.88 0.88 1.83 0.33 2.75 ... -0.62 3.44 -0.54 0.6 1.68 0.5 0.25 -0.38 1.84 0.88
Payoff Ratio 1.0 0.95 0.95 0.93 0.93 0.93 0.93 1.03 0.86 1.0 ... 1.08 1.67 1.23 1.17 1.05 1.0 0.98 1.08 1.01 0.93
Profit Factor 1.24 1.16 1.19 1.15 1.15 1.15 1.15 1.22 1.07 1.2 ... 0.85 2.3 0.87 1.08 1.21 1.08 1.04 0.87 1.24 1.15
Common Sense Ratio 1.38 1.17 1.21 1.07 1.07 1.07 1.07 1.24 0.91 1.16 ... 0.85 NaN 0.77 1.22 1.27 1.05 1.02 0.73 1.25 1.07
CPC Index 0.69 0.6 0.63 0.59 0.59 0.59 0.59 0.68 0.51 0.65 ... 0.41 2.23 0.45 0.61 0.68 0.56 0.53 0.42 0.69 0.59
Tail Ratio 1.11 1.01 1.01 0.93 0.93 0.93 0.93 1.01 0.86 0.97 ... 0.99 NaN 0.89 1.13 1.04 0.98 0.98 0.83 1.01 0.93
Outlier Win Ratio 3.42 3.51 3.52 3.55 3.55 3.55 3.55 3.38 3.59 3.33 ... 4.4 24.7 9.97 3.94 3.34 3.8 3.79 9.97 3.7 3.55
Outlier Loss Ratio 3.76 3.64 3.64 3.6 3.6 3.6 3.6 3.82 3.39 3.64 ... 3.36 0.67 3.22 3.16 3.0 3.17 3.41 3.12 3.82 3.6
MTD 0.02 0.02 0.02 0.02 0.02 0.02 0.02 0.01 0.02 0.02 ... -0.04 0.0 -0.01 -0.03 0.02 0.02 0.0 -0.02 0.02 0.02
3M 0.05 0.05 0.05 0.05 0.05 0.05 0.05 0.04 0.03 0.05 ... -0.11 0.0 -0.04 -0.06 0.05 -0.02 -0.08 -0.04 0.05 0.05
6M 0.19 0.16 0.21 0.21 0.21 0.21 0.21 0.17 0.02 0.12 ... -0.16 0.01 -0.04 0.0 0.21 0.03 0.03 -0.02 0.21 0.21
YTD 0.35 0.21 0.26 0.2 0.2 0.2 0.2 0.31 0.06 0.25 ... -0.21 0.1 -0.12 0.08 0.27 0.08 0.03 -0.11 0.32 0.2
1Y 0.35 0.21 0.26 0.2 0.2 0.2 0.2 0.31 0.06 0.25 ... -0.21 0.1 -0.12 0.08 0.27 0.08 0.03 -0.11 0.32 0.2
3Y (ann.) 0.35 0.21 0.27 0.2 0.2 0.2 0.2 0.32 0.07 0.26 ... -0.22 0.1 -0.12 0.08 0.27 0.08 0.03 -0.11 0.33 0.2
5Y (ann.) 0.35 0.21 0.27 0.2 0.2 0.2 0.2 0.32 0.07 0.26 ... -0.22 0.1 -0.12 0.08 0.27 0.08 0.03 -0.11 0.33 0.2
10Y (ann.) 0.35 0.21 0.27 0.2 0.2 0.2 0.2 0.32 0.07 0.26 ... -0.22 0.1 -0.12 0.08 0.27 0.08 0.03 -0.11 0.33 0.2
All-time (ann.) 0.35 0.21 0.27 0.2 0.2 0.2 0.2 0.32 0.07 0.26 ... -0.22 0.1 -0.12 0.08 0.27 0.08 0.03 -0.11 0.33 0.2
Best Day 0.07 0.07 0.07 0.07 0.07 0.07 0.07 0.07 0.05 0.05 ... 0.07 0.06 0.07 0.07 0.04 0.07 0.05 0.05 0.07 0.07
Worst Day -0.05 -0.05 -0.05 -0.05 -0.05 -0.05 -0.05 -0.05 -0.06 -0.06 ... -0.05 -0.04 -0.06 -0.04 -0.05 -0.04 -0.05 -0.06 -0.05 -0.05
Best Month 0.11 0.09 0.09 0.09 0.09 0.09 0.09 0.11 0.11 0.11 ... 0.04 0.13 0.05 0.09 0.11 0.09 0.09 0.05 0.11 0.09
Worst Month -0.11 -0.11 -0.11 -0.11 -0.11 -0.11 -0.11 -0.09 -0.12 -0.07 ... -0.07 -0.03 -0.09 -0.05 -0.07 -0.06 -0.09 -0.09 -0.08 -0.11
Best Year 0.35 0.21 0.26 0.2 0.2 0.2 0.2 0.31 0.06 0.25 ... -0.21 0.1 -0.12 0.08 0.27 0.08 0.03 -0.11 0.32 0.2
Worst Year 0.35 0.21 0.26 0.2 0.2 0.2 0.2 0.31 0.06 0.25 ... -0.21 0.1 -0.12 0.08 0.27 0.08 0.03 -0.11 0.32 0.2
Avg. Drawdown -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.03 -0.06 -0.03 ... -0.09 -0.02 -0.06 -0.04 -0.04 -0.05 -0.04 -0.09 -0.03 -0.03
Avg. Drawdown Days 11 14 13 15 15 15 15 13 31 23 ... 43 33 50 43 33 34 28 174 11 15
Recovery Factor 1.56 0.8 1.03 0.71 0.71 0.71 0.71 1.42 0.38 1.36 ... -0.8 2.54 -0.58 0.48 1.23 0.52 0.16 -0.64 1.62 0.71
Ulcer Index 1.05 1.06 1.06 1.26 1.26 1.26 1.26 1.42 1.44 1.05 ... 1.13 inf inf 1.06 1.04 1.11 1.1 1.02 1.41 1.26
Avg. Up Month 0.06 0.04 0.05 0.05 0.05 0.05 0.05 0.06 0.05 0.04 ... 0.03 0.03 0.02 0.05 0.05 0.04 0.04 0.03 0.05 0.05

60 rows × 21 columns

Persist Backtest to DB (optional )
In [ ]:
session.add( tsExecuteEngine )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst)
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")

Portfolio H

Portfolio H: Utilized Leveraged ETFs for Trading on The Model Security

- All models are trained on their corresponding US Index/model, but the trade enter via a broker is with
  the underlying leveraged ETF.

- ETF data for US Indixes not available until 2011 in yahoo finance

- Five Trade Strategies are executed with ETF on, and Five with ETF off to show effect of ETF trading

- Additionally, there is a composite trade strategy for all ETF strategies and one for non-ETF 
  trade strategies

Backtest:

1. Type: regular

2. AI Models Fit Date Ranges
    1. Training Period: 
        1. Begin Date = 2007-01-01 
        2. End Date   = 2012-12-31  
    2. Validation Period: 
        1. Begin Date = 2013-01-01 
        2. End Date   = 2014-12-31 

3. Test Period: 
    1. Begin Date = 2015-01-01 
    2. End Date   = 2015-12-31         
Portfolio Trade Assets
In [167]:
portfolio_trade_assets   = [ "^DJI", "^IXIC", "^GSPC" ]
Market Data Manager
In [168]:
dirPathMarketData = '/Users/gustavozambrana/Google Drive/Python/Projects/Trade_Engine/Data/US_Market_Indixes'

supportedTradeAssets   = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str           = "2000-01-01"
end_date_str           = None

ts_marketdat_mng = TradeStrategyMarketDataMng(\
        marketDataProviderName = "yahoofinance",
        supportedTradeAssets   = supportedTradeAssets,
        stock_price_col_name   = "Adj Close",
        fileNameMarketData     = "US_Indixes_And_ETFs_MrkData",
        dirPathMarketData      = dirPathMarketData,
        beg_date_str           = beg_date_str,
        end_date_str           = end_date_str,
        interval               = "1d"  ) 
2021-10-28 20:53:17,844 [INFO] root: Found previous Market data previously loaded to specified file and dir.
In [171]:
MarketData.getDateRangesForStocks( ts_marketdat_mng.marketDataObj.getDataFrame() )
Out[171]:
Index Beg_Date End_Date
0 ^DJI 2000-01-03 2021-09-20
1 ^GSPC 2000-01-03 2021-09-20
2 ^IXIC 2000-01-03 2021-09-20
3 SPXL 2008-11-05 2021-09-20
4 SPXS 2008-11-19 2021-09-20
5 SDOW 2010-02-11 2021-09-20
6 SQQQ 2010-02-11 2021-09-20
7 TQQQ 2010-02-11 2021-09-20
8 UDOW 2010-02-11 2021-09-20
Pipeline Data Manager
In [172]:
ts_model_pipline_mng_h = TradeStrategyModelPipelineDataMng(\
                            tsMarketDataMng    = ts_marketdat_mng,
                            package            = "trade_engine.model.ai.WaveNet_RNN_AI_PipelineBuilder",
                            model_class_name   = "WaveNet_RNN_AI_PipelineBuilder",
                            fileNameMarketData = "WaveNet_RNN_AI_Pipeline_Data_Portf_H",
                            forceCreatePipelineData = True,
                            dirPathMarketData  = dirPathMarketData )
Simulation Broker
In [173]:
brokerTradingObj = SimBrokerTrading()
Trade Strategies, Trade Investment Manager, and Trade Asset Register Items
In [174]:
tsConfDat = TradeStrategyConfigData()

# Set Config

tsConfDat.tsSetConfig(\
    ts_set_conf_dict = 
           { 'set_actions_conf' : 
                      { "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
                        "exit"  : { 'votingPolicy' : 1, 
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1 } 
                      }
           } )

# TS #1

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_gru", 
    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "gru",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'         : 20 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 1, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },

                               "stop_lost" :
                                    { 'model'    : "fix_perc",
                                      'type'     : "ta",
                                      'obj_args' : { 'long_stop_los_per' : 5, 'short_stop_los_per'    : 5 }  } 
                             },
                    }  )

# TS #2

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_lstm", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'         : 50,   'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn'   : True,
                                                 'epochs'          : 20 }  
                                }
                            } }  )

# TS #3

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_bb",    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "bb",
                                  'type'     : "ta",
                                  'obj_args' : { 'window' : 13, 'window_dev' : 1 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 },
                                },
                            }  } )
# TS #4

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_macd",    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "macd",
                                  'type'     : "ta",
                                  'obj_args' : { 'window_slow' : 26, 'window_fast' : 12, 'window_sign' : 9,
                                                 'enter_long_macd_diff'  : 0.5 , 'exi_long_macd_diff' : 0.5,
                                                 'enter_short_macd_diff' : -0.5, 'exi_short_macd_diff' : -0.5  },
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 },
                                },
                            }  } )
# TS #5

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_rsi",    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "rsi",
                                  'type'     : "ta",
                                  'obj_args' : { 'rsi_enter_long'  : 30.0,  'rsi_exit_long'  : 30.0, 
                                                 'rsi_enter_short' : 70.0,  'rsi_exit_short' : 70.0 },
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 },
                                },
                            }  } )
In [175]:
taRegisterItems = [ ]
tsActionGen = TradeStrategyActionGenerator()

# **** Configure ETF based Trade Strategies

for trade_asset in portfolio_trade_assets :
    
    num_ts = len(tsConfDat.name_list) + 1  # adding the composite  trade strategy
    
    for i in range( num_ts ) :

        if i <= num_ts - 2:
            # *** Trade Strategy 

            actionDatItem  = tsConfDat.getTSConfigDataForItem(item_num = i )
            ts_unique_name = actionDatItem.name_list[0]
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = actionDatItem,
                                                     pipelineMng       = ts_model_pipline_mng_h )
        else :
            # Composite Trade Strategy 
            
            ts_unique_name = "all"            
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = tsConfDat,
                                                     pipelineMng       = ts_model_pipline_mng_h )

        ts_model = TradeStrategyBaseModelPersist(\
                        trade_asset               = trade_asset,
                        trade_on_ETFs          =  True,
                        trade_assets_etf_map   = { "^DJI"  : [ "UDOW", "SDOW"], 
                                                   "^IXIC" : [ "TQQQ", "SQQQ"], 
                                                   "^GSPC" : [ "SPXL", "SPXS"] }, 
                        ts_marketdat_mng          = ts_marketdat_mng,
                        ts_enter                  = trade_enter_set,
                        ts_exit                   = trade_exit_set,                       
                        model_type                = ts_unique_name,
                        model_version             = "1.0",
                        market_data_period        = MarketDataPeriod.Day,
                    ) 

        # *** Trade Strategy Investment Manager 

        taInvMng = TradingAssetInvMngBase(\
                                        trade_asset                = trade_asset,
                                        minPeriodsBetweenTrades    = 1,
                                        initInvestment             = 1000000.0, 
                                        capPercentToInvestPerTrade = 100.0,
                                        minInvestPercent           = 5.0,
                                        min_account_balance        = 1000.0 )

        # *** Trade Register Item
        # *** This object has all configuration defined to execute a given trade strategy,
        # *** It can be executed individually in backtest or as part of a portfolio

        ta_registered_item = TradingAssetRegisterItem(\
                trade_name                    = "{0}_{1}_etf".format(ts_unique_name, trade_asset), 
                ts_model                      = ts_model,
                tradingExecutionType          = TradingAssetExecutionType.Simulation,
                tradingBrokerObj              = brokerTradingObj,
                tradingAssetInvMngObj         = taInvMng )  

        taRegisterItems.append(ta_registered_item)

# **** Configure Non-ETF based Trade Strategies (for comparison)
        
for trade_asset in portfolio_trade_assets :
    
    num_ts = len(tsConfDat.name_list) + 1  # adding the composite  trade strategy
    
    for i in range( num_ts ) :

        if i <= num_ts - 2:
            # *** Trade Strategy 

            actionDatItem  = tsConfDat.getTSConfigDataForItem(item_num = i )
            ts_unique_name = actionDatItem.name_list[0]
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = actionDatItem,
                                                     pipelineMng       = ts_model_pipline_mng_h )
        else :
            # Composite Trade Strategy 
            
            ts_unique_name = "all"            
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = tsConfDat,
                                                     pipelineMng       = ts_model_pipline_mng_h )

        ts_model = TradeStrategyBaseModelPersist(\
                        trade_asset               = trade_asset,
                        trade_on_ETFs          =  False,
                        trade_assets_etf_map   = { "^DJI"  : [ "UDOW", "SDOW"], 
                                                   "^IXIC" : [ "TQQQ", "SQQQ"], 
                                                   "^GSPC" : [ "SPXL", "SPXS"] }, 
                        ts_marketdat_mng          = ts_marketdat_mng,
                        ts_enter                  = trade_enter_set,
                        ts_exit                   = trade_exit_set,                       
                        model_type                = ts_unique_name,
                        model_version             = "1.0",
                        market_data_period        = MarketDataPeriod.Day,
                    ) 

        # *** Trade Strategy Investment Manager 

        taInvMng = TradingAssetInvMngBase(\
                                        trade_asset                = trade_asset,
                                        minPeriodsBetweenTrades    = 1,
                                        initInvestment             = 1000000.0, 
                                        capPercentToInvestPerTrade = 100.0,
                                        minInvestPercent           = 5.0,
                                        min_account_balance        = 1000.0 )

        # *** Trade Register Item
        # *** This object has all configuration defined to execute a given trade strategy,
        # *** It can be executed individually in backtest or as part of a portfolio

        ta_registered_item = TradingAssetRegisterItem(\
                trade_name                    = "{0}_{1}".format(ts_unique_name, trade_asset), 
                ts_model                      = ts_model,
                tradingExecutionType          = TradingAssetExecutionType.Simulation,
                tradingBrokerObj              = brokerTradingObj,
                tradingAssetInvMngObj         = taInvMng )  

        taRegisterItems.append(ta_registered_item)
        
In [176]:
print("Number of configured Trade Asset Register Items: ", len(taRegisterItems) )
Number of configured Trade Asset Register Items:  36
Portfolio Investment Manager
In [177]:
# *** Porttfolio Investment Manager across all individual trade strategies investment managers
# *** Role: 
# ***    1) Managed investment funds across n number of trade strategies
# ***    2) Rebalance portfolio periodically or never
# ***    3) Portfolio Policy Weights 
# ***          equal weights (default)
# ***          MinimumVariance
# ***          User defined 
# ***    4) Track Portfolio level returns and metrics
# ***          Individual Trade Strategies return and metrics tracked through their 
# ***          investment managers
# ***          Portfolio funds are split across each trade strategy investment manager based on the
# ***          portfolio weights

portfInvMng = PortfolioInvMng(\
                  name                       = "Portfolio Inv. Manager for US-Indexes - Using ETFs for Trading",
                  initInvestment             = 2000000.0 * ( len(taRegisterItems) + 3),  # 200K/trade-strag
                  portfRebalanceFreq         = PortfolioRebalanceFrequency.Never,
                  portfRebalancePeriods      = 1,
                  minInvestPercent           = 5.0,
                  min_account_balance        = 1000.0,     
                  minPeriodsBetweenTrades    = 1,
                  capPercentToInvestPerTrade = 100.0 )
Trade Register Items Portfolio
In [178]:
# *** Set of Trade Register Items
#
# Configuration Summary:
#    - Each set has 1 to n trade register items as previously described 
#    - Optionally add long only trade strategies for all unique trade assets in the
#      portfolio 
#           - (Dow, Nasdaq, and S&P 500 for this portfolio) in this example
#           - Might be useful for bench marking trade strategies
#    - Each set has one Investment Portfolio Manager
#       - portfolio funds allocated per portfolio policy rules and re-balanced (if defined), 
#         across all trade strategies


portf_registered_obj = PortfolioRegisterItem(\
                        name                 = "Portfolio H, US-Indexes - Using ETFs for Trading, and Long strategies",
                        taRegisterItems      = taRegisterItems,
                        portfolioInvMngObj   = portfInvMng,
                        tradingExecutionType = TradingAssetExecutionType.Simulation,
                        add_long_only_ts     = True )
2021-10-28 20:56:22,949 [INFO] root: *** Adding long only trade strategies for : {'^GSPC', '^IXIC', '^DJI'}
Persist to DB (optional)
In [ ]:
session.add( portf_registered_obj )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")
Re-Store from DB (optional)
In [ ]:
session.expunge_all()
del portf_registered_obj

for tsObj in session.query(PortfolioRegisterItem):  
    print(tsObj.name)
    if  tsObj.name  == "Portfolio H, US-Indexes - Using ETFs for Trading, and Long strategies" :
        break

portf_registered_obj = tsObj
print(portf_registered_obj.id, portf_registered_obj.name)
Training, Validation and Test Periods for Backtest

In Order to backtest a trade strategy or portfolio that has AI models, the following data is required:

  1. Training Date Range

    1. Date range that will be used to train the AI models in the backtest
  2. Validation Date Range

    1. Date range that twill be used to validate the AI models, should not overlapped with the training date range
  3. Test Period Date Range

    1. This is the out-sample date range, which corresponds to the date range of the backtest

Date Ranges are defined with a DatasetDef object, and have the following parameters:

  1. strBegDateAIModels : Date to begin training or validation of an AI model
  2. strBegDate : Date to begin the backtest
  3. strEndDate : Date to end training, validation and Backtest

Note:

  1. The param strBegDateAIModels can be defined as the same date as strBegDate, that is the default, if not defined.
  2. The critical aspect of using this parameter is in the backtest. Some AI Models, such as time series, others using moving averages over many periods, create params with no predicting data for those initial dates. Thus, in order to ensure the backtest starts on the actual date specified, the strBegDateAIModels should be defined as an earlier date, and it should not overlapped with the validation period end-date to avoid any chance of bias by picking at the validation data.
In [179]:
training_period = DatasetDef(datasetType = DatasetType.Training,
                             strBegDateAIModels = "2006-07-01",
                             strBegDate         = "2007-01-01",
                             strEndDate         = "2012-12-31" )

validation_period = DatasetDef(datasetType = DatasetType.Validation,
                               strBegDateAIModels = "2012-07-01",
                               strBegDate         = "2013-01-01",
                               strEndDate         = "2014-12-31" )

testing_period = DatasetDef(datasetType = DatasetType.Testing,
                               strBegDateAIModels = "2014-07-01",
                               strBegDate         = "2015-01-01",
                               strEndDate         = "2015-12-31" )

fit_datasets = FitDatasetsDef( trainingDataset    = training_period,
                               validationDataset  = validation_period )
Execute Backtest
In [180]:
tsExecuteEngine = BacktestExecution( \
                    name = "Backtest for Portfolio H",
                    timePeriod  = testing_period,
                    fitDatasets = fit_datasets,
                    trade_asset_registered_item = portf_registered_obj )
In [ ]:
tsExecuteEngine.evaluate()
Backtest Metrics
Trade Strategies Execution & Investment Metrics

DOW Jones

In [183]:
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
        'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
        query('TA_Reg_Name.str.contains("DJI")', engine='python')
Out[183]:
TA_Reg_Name Is_Portfolio Num_Trades_Completed Init_Capital Final_Capital Cum_Return Backtest_Status
1 ts_gru_^DJI_etf No 85 2000000.0 1.971196e+06 -0.014402 Completed
2 ts_lstm_^DJI_etf No 31 2000000.0 1.889744e+06 -0.055128 Completed
3 ts_bb_^DJI_etf No 60 2000000.0 2.855684e+06 0.427842 Completed
4 ts_macd_^DJI_etf No 21 2000000.0 2.433666e+06 0.216833 Completed
5 ts_rsi_^DJI_etf No 4 2000000.0 2.025475e+06 0.012738 Completed
6 all_^DJI_etf No 103 2000000.0 1.801438e+06 -0.099281 Completed
19 ts_gru_^DJI No 85 2000000.0 2.269268e+06 0.134634 Completed
20 ts_lstm_^DJI No 31 2000000.0 2.466724e+06 0.233362 Completed
21 ts_bb_^DJI No 60 2000000.0 2.365050e+06 0.182525 Completed
22 ts_macd_^DJI No 21 2000000.0 1.868237e+06 -0.065882 Completed
23 ts_rsi_^DJI No 4 2000000.0 2.087736e+06 0.043868 Completed
24 all_^DJI No 103 2000000.0 2.484117e+06 0.242058 Completed
39 Long-Only Trade Strategy for ^DJI No 1 2000000.0 1.954308e+06 -0.022846 Completed

Nasdaq

In [184]:
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
        'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
        query('TA_Reg_Name.str.contains("IXIC")', engine='python')
Out[184]:
TA_Reg_Name Is_Portfolio Num_Trades_Completed Init_Capital Final_Capital Cum_Return Backtest_Status
7 ts_gru_^IXIC_etf No 59 2000000.0 2.486847e+06 0.243423 Completed
8 ts_lstm_^IXIC_etf No 23 2000000.0 2.596818e+06 0.298409 Completed
9 ts_bb_^IXIC_etf No 54 2000000.0 2.479309e+06 0.239655 Completed
10 ts_macd_^IXIC_etf No 22 2000000.0 3.120366e+06 0.560183 Completed
11 ts_rsi_^IXIC_etf No 4 2000000.0 2.133742e+06 0.066871 Completed
12 all_^IXIC_etf No 71 2000000.0 2.261971e+06 0.130986 Completed
25 ts_gru_^IXIC No 59 2000000.0 1.849588e+06 -0.075206 Completed
26 ts_lstm_^IXIC No 23 2000000.0 2.381274e+06 0.190637 Completed
27 ts_bb_^IXIC No 54 2000000.0 2.589623e+06 0.294811 Completed
28 ts_macd_^IXIC No 22 2000000.0 1.694798e+06 -0.152601 Completed
29 ts_rsi_^IXIC No 4 2000000.0 2.100902e+06 0.050451 Completed
30 all_^IXIC No 71 2000000.0 1.925470e+06 -0.037265 Completed
38 Long-Only Trade Strategy for ^IXIC No 1 2000000.0 2.118694e+06 0.059347 Completed

S&P 500

In [185]:
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
        'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
        query('TA_Reg_Name.str.contains("GSPC")', engine='python')
Out[185]:
TA_Reg_Name Is_Portfolio Num_Trades_Completed Init_Capital Final_Capital Cum_Return Backtest_Status
13 ts_gru_^GSPC_etf No 75 2000000.0 1.980361e+06 -0.009820 Completed
14 ts_lstm_^GSPC_etf No 24 2000000.0 2.060605e+06 0.030303 Completed
15 ts_bb_^GSPC_etf No 59 2000000.0 2.556850e+06 0.278425 Completed
16 ts_macd_^GSPC_etf No 31 2000000.0 2.483369e+06 0.241685 Completed
17 ts_rsi_^GSPC_etf No 3 2000000.0 2.016714e+06 0.008357 Completed
18 all_^GSPC_etf No 93 2000000.0 1.860754e+06 -0.069623 Completed
31 ts_gru_^GSPC No 75 2000000.0 2.303542e+06 0.151771 Completed
32 ts_lstm_^GSPC No 24 2000000.0 2.430980e+06 0.215490 Completed
33 ts_bb_^GSPC No 59 2000000.0 2.233747e+06 0.116873 Completed
34 ts_macd_^GSPC No 31 2000000.0 1.612727e+06 -0.193636 Completed
35 ts_rsi_^GSPC No 3 2000000.0 2.078932e+06 0.039466 Completed
36 all_^GSPC No 93 2000000.0 2.134662e+06 0.067331 Completed
37 Long-Only Trade Strategy for ^GSPC No 1 2000000.0 1.986154e+06 -0.006923 Completed
Performance Metrics
In [189]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
        query('trade_asset == "^DJI"' )
Out[189]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
1 ts_gru_^DJI_etf No ts_gru ^DJI 2015-01-05 2015-12-31 0.99 -0.01 -0.01 0.19 -0.36 0.12 -0.11
2 ts_lstm_^DJI_etf No ts_lstm ^DJI 2015-01-05 2015-12-31 0.99 -0.06 -0.06 0.1 -0.37 0.12 -0.11
3 ts_bb_^DJI_etf No ts_bb ^DJI 2015-01-05 2015-12-31 0.65 0.43 0.43 1.13 -0.29 0.12 -0.11
4 ts_macd_^DJI_etf No ts_macd ^DJI 2015-01-05 2015-12-31 0.91 0.22 0.22 0.64 -0.33 0.2 -0.13
5 ts_rsi_^DJI_etf No ts_rsi ^DJI 2015-01-05 2015-12-31 0.02 0.01 0.01 0.16 -0.14 0.12 -0.11
6 all_^DJI_etf No all ^DJI 2015-01-05 2015-12-31 0.91 -0.1 -0.1 -0.03 -0.39 0.12 -0.11
19 ts_gru_^DJI No ts_gru ^DJI 2015-01-05 2015-12-31 1.0 0.13 0.14 0.9 -0.11 0.04 -0.04
20 ts_lstm_^DJI No ts_lstm ^DJI 2015-01-05 2015-12-31 1.0 0.23 0.24 1.45 -0.12 0.04 -0.04
21 ts_bb_^DJI No ts_bb ^DJI 2015-01-05 2015-12-31 0.65 0.18 0.19 1.36 -0.08 0.04 -0.04
22 ts_macd_^DJI No ts_macd ^DJI 2015-01-05 2015-12-31 0.92 -0.07 -0.07 -0.4 -0.15 0.03 -0.03
23 ts_rsi_^DJI No ts_rsi ^DJI 2015-01-05 2015-12-31 0.02 0.04 0.04 0.75 -0.02 0.04 -0.02
24 all_^DJI No all ^DJI 2015-01-05 2015-12-31 0.92 0.24 0.25 1.57 -0.1 0.04 -0.04
39 Long-Only Trade Strategy for ^DJI No long ^DJI 2015-01-05 2015-12-31 1.0 -0.02 -0.02 -0.07 -0.14 0.04 -0.04
In [190]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
        query('trade_asset == "^IXIC"' )
Out[190]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
7 ts_gru_^IXIC_etf No ts_gru ^IXIC 2015-01-05 2015-12-31 1.0 0.24 0.25 0.68 -0.36 0.14 -0.12
8 ts_lstm_^IXIC_etf No ts_lstm ^IXIC 2015-01-05 2015-12-31 1.0 0.3 0.3 0.76 -0.36 0.14 -0.12
9 ts_bb_^IXIC_etf No ts_bb ^IXIC 2015-01-05 2015-12-31 0.63 0.24 0.24 0.71 -0.35 0.14 -0.12
10 ts_macd_^IXIC_etf No ts_macd ^IXIC 2015-01-05 2015-12-31 0.93 0.56 0.57 1.0 -0.44 0.34 -0.19
11 ts_rsi_^IXIC_etf No ts_rsi ^IXIC 2015-01-05 2015-12-31 0.04 0.07 0.07 0.42 -0.14 0.14 -0.12
12 all_^IXIC_etf No all ^IXIC 2015-01-05 2015-12-31 0.93 0.13 0.13 0.5 -0.39 0.14 -0.12
25 ts_gru_^IXIC No ts_gru ^IXIC 2015-01-05 2015-12-31 1.0 -0.08 -0.08 -0.38 -0.19 0.04 -0.04
26 ts_lstm_^IXIC No ts_lstm ^IXIC 2015-01-05 2015-12-31 1.0 0.19 0.19 1.12 -0.1 0.04 -0.04
27 ts_bb_^IXIC No ts_bb ^IXIC 2015-01-05 2015-12-31 0.63 0.29 0.3 1.89 -0.08 0.04 -0.04
28 ts_macd_^IXIC No ts_macd ^IXIC 2015-01-05 2015-12-31 0.93 -0.15 -0.15 -0.99 -0.21 0.03 -0.03
29 ts_rsi_^IXIC No ts_rsi ^IXIC 2015-01-05 2015-12-31 0.04 0.05 0.05 0.82 -0.02 0.04 -0.02
30 all_^IXIC No all ^IXIC 2015-01-05 2015-12-31 0.93 -0.04 -0.04 -0.15 -0.16 0.04 -0.04
38 Long-Only Trade Strategy for ^IXIC No long ^IXIC 2015-01-05 2015-12-31 1.0 0.06 0.06 0.43 -0.14 0.04 -0.04
In [191]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
        query('trade_asset == "^GSPC"' )
Out[191]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
13 ts_gru_^GSPC_etf No ts_gru ^GSPC 2015-01-05 2015-12-31 1.0 -0.01 -0.01 0.21 -0.33 0.12 -0.12
14 ts_lstm_^GSPC_etf No ts_lstm ^GSPC 2015-01-05 2015-12-31 1.0 0.03 0.03 0.29 -0.32 0.12 -0.12
15 ts_bb_^GSPC_etf No ts_bb ^GSPC 2015-01-05 2015-12-31 0.64 0.28 0.28 0.83 -0.3 0.12 -0.12
16 ts_macd_^GSPC_etf No ts_macd ^GSPC 2015-01-05 2015-12-31 0.87 0.24 0.25 0.68 -0.29 0.21 -0.15
17 ts_rsi_^GSPC_etf No ts_rsi ^GSPC 2015-01-05 2015-12-31 0.02 0.01 0.01 0.14 -0.16 0.12 -0.13
18 all_^GSPC_etf No all ^GSPC 2015-01-05 2015-12-31 0.93 -0.07 -0.07 0.05 -0.39 0.12 -0.12
31 ts_gru_^GSPC No ts_gru ^GSPC 2015-01-05 2015-12-31 1.0 0.15 0.15 0.99 -0.1 0.04 -0.04
32 ts_lstm_^GSPC No ts_lstm ^GSPC 2015-01-05 2015-12-31 1.0 0.22 0.22 1.33 -0.1 0.04 -0.04
33 ts_bb_^GSPC No ts_bb ^GSPC 2015-01-05 2015-12-31 0.64 0.12 0.12 0.9 -0.08 0.04 -0.04
34 ts_macd_^GSPC No ts_macd ^GSPC 2015-01-05 2015-12-31 0.87 -0.19 -0.2 -1.44 -0.22 0.04 -0.03
35 ts_rsi_^GSPC No ts_rsi ^GSPC 2015-01-05 2015-12-31 0.02 0.04 0.04 0.66 -0.02 0.04 -0.02
36 all_^GSPC No all ^GSPC 2015-01-05 2015-12-31 0.93 0.07 0.07 0.51 -0.08 0.04 -0.04
37 Long-Only Trade Strategy for ^GSPC No long ^GSPC 2015-01-05 2015-12-31 1.0 -0.01 -0.01 0.03 -0.12 0.04 -0.04
In [ ]:
tsExecuteEngine.getSummaryMetrics().T.head(60)
Persist Backtest to DB (optional )
In [ ]:
session.add( tsExecuteEngine )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst)
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")

Portfolio I

Portfolio I: Monthly Rebalance of Funds in the Portfolio

- Same strategies as defined and explained in Portfolio C.

- Only difference is the Portfolio Investment Manager is configured to balance funds monthly, 
  using an equal weights policy.

Backtest:

1. Type: regular

2. Test Period: 
    1. Begin Date = 2012-01-01 
    2. End Date   = 2015-12-31   
Portfolio Trade Assets
In [192]:
portfolio_trade_assets   = [ "^DJI", "^IXIC", "^GSPC" ]
Market Data Manager
In [193]:
dirPathMarketData = '/Users/gustavozambrana/Google Drive/Python/Projects/Trade_Engine/Data/US_Market_Indixes'

supportedTradeAssets   = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str           = "2000-01-01"
end_date_str           = None

ts_marketdat_mng = TradeStrategyMarketDataMng(\
        marketDataProviderName = "yahoofinance",
        supportedTradeAssets   = supportedTradeAssets,
        stock_price_col_name   = "Adj Close",
        fileNameMarketData     = "US_Indixes_And_ETFs_MrkData",
        dirPathMarketData      = dirPathMarketData,
        beg_date_str           = beg_date_str,
        end_date_str           = end_date_str,
        interval               = "1d"  ) 
2021-10-28 21:40:46,355 [INFO] root: Found previous Market data previously loaded to specified file and dir.
Simulation Broker
In [194]:
brokerTradingObj = SimBrokerTrading()
Trade Strategies, Trade Investment Manager, and Trade Asset Register Items
In [195]:
tsConfDat = TradeStrategyConfigData()

# Set Config

tsConfDat.tsSetConfig(\
    ts_set_conf_dict = 
           { 'set_actions_conf' : 
                      { "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
                        "exit"  : { 'votingPolicy' : 1, 
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1 } 
                      }
           } )
           
# TS #1

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_1",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 20, 'win_slow' : 100 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : True },
                                  'exit_policy_args'   : { 'lastn_match' : 2 } },
                             },
                    }  )

# TS #2

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_2",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 10, 'win_slow' : 50 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : True },
                                  'exit_policy_args'   : { 'lastn_match' : 2 } },
                             },
                    }  )

# TS #3

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_3",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 10, 'win_slow' : 50 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : True },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },
                             },
                    }  )

# TS #4

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_4",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 15, 'win_slow' : 60 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : True },
                                  'exit_policy_args'   : { 'lastn_match' : 2 } },
                             },
                    }  )

# TS #5

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_5",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 15, 'win_slow' : 75 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : True },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },
                             },
                    }  )

# TS #6

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_6",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 7, 'win_slow' : 35 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : True },
                                  'exit_policy_args'   : { 'lastn_match' : 2 } },
                             },
                    }  )

# TS #7

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_7",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 7, 'win_slow' : 35 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : True },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },
                             },
                    }  )
In [196]:
taRegisterItems = [ ]
tsActionGen = TradeStrategyActionGenerator()

for trade_asset in portfolio_trade_assets :
    
    num_ts = len(tsConfDat.name_list) + 1  # adding the composite  trade strategy
    
    for i in range( num_ts ) :

        if i <= num_ts - 2:
            # *** Trade Strategy 

            actionDatItem  = tsConfDat.getTSConfigDataForItem(item_num = i )
            ts_unique_name = actionDatItem.name_list[0]
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = actionDatItem,
                                                     pipelineMng       = None )
        else :
            # Composite Trade Strategy 
            
            ts_unique_name = "all"            
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = tsConfDat,
                                                     pipelineMng       = None )

        ts_model = TradeStrategyBaseModelPersist(\
                        trade_asset               = trade_asset,
                        ts_marketdat_mng          = ts_marketdat_mng,
                        ts_enter                  = trade_enter_set,
                        ts_exit                   = trade_exit_set,                       
                        model_type                = ts_unique_name,
                        model_version             = "1.0",
                        market_data_period        = MarketDataPeriod.Day,
                    ) 

        # *** Trade Strategy Investment Manager 

        taInvMng = TradingAssetInvMngBase(\
                                        trade_asset                = trade_asset,
                                        minPeriodsBetweenTrades    = 1,
                                        initInvestment             = 1000000.0, 
                                        capPercentToInvestPerTrade = 100.0,
                                        minInvestPercent           = 5.0,
                                        min_account_balance        = 1000.0 )

        # *** Trade Register Item
        # *** This object has all configuration defined to execute a given trade strategy,
        # *** It can be executed individually in backtest or as part of a portfolio

        ta_registered_item = TradingAssetRegisterItem(\
                trade_name                    = "{0}_{1}".format(ts_unique_name, trade_asset), 
                ts_model                      = ts_model,
                tradingExecutionType          = TradingAssetExecutionType.Simulation,
                tradingBrokerObj              = brokerTradingObj,
                tradingAssetInvMngObj         = taInvMng )  

        taRegisterItems.append(ta_registered_item)
In [197]:
print("Number of configured Trade Asset Register Items: ", len(taRegisterItems) )
Number of configured Trade Asset Register Items:  24
Portfolio Investment Manager
In [198]:
# *** Porttfolio Investment Manager across all individual trade strategies investment managers
# *** Role: 
# ***    1) Managed investment funds across n number of trade strategies
# ***    2) Rebalance portfolio periodically or never
# ***    3) Portfolio Policy Weights 
# ***          equal weights (default)
# ***          MinimumVariance
# ***          User defined 
# ***    4) Track Portfolio level returns and metrics
# ***          Individual Trade Strategies return and metrics tracked through their 
# ***          investment managers
# ***          Portfolio funds are split across each trade strategy investment manager based on the
# ***          portfolio weights

portfInvMng = PortfolioInvMng(\
                  name                       = "Portfolio Inv. Manager for US-Indexes - Montly-Rebalance TS",
                  initInvestment             = 2000000.0 * ( len(taRegisterItems) + 3),  # 200K/trade-strag
                  portfRebalanceFreq         = PortfolioRebalanceFrequency.Monthly, # Monthly Rebalance
                  portfRebalancePeriods      = 1,
                  minInvestPercent           = 5.0,
                  min_account_balance        = 1000.0,     
                  minPeriodsBetweenTrades    = 1,
                  capPercentToInvestPerTrade = 100.0 )
Trade Register Items Portfolio
In [199]:
# *** Set of Trade Register Items
#
# Configuration Summary:
#    - Each set has 1 to n trade register items as previously described 
#    - Optionally add long only trade strategies for all unique trade assets in the
#      portfolio 
#           - (Dow, Nasdaq, and S&P 500 for this portfolio) in this example
#           - Might be useful for bench marking trade strategies
#    - Each set has one Investment Portfolio Manager
#       - portfolio funds allocated per portfolio policy rules and re-balanced (if defined), 
#         across all trade strategies


portf_registered_obj = PortfolioRegisterItem(\
                        name                 = "Portfolio Inv. Manager for US-Indexes - Montly-Rebalance TS",
                        taRegisterItems      = taRegisterItems,
                        portfolioInvMngObj   = portfInvMng,
                        tradingExecutionType = TradingAssetExecutionType.Simulation,
                        add_long_only_ts     = True )
Persist to DB (optional)
In [ ]:
session.add( portf_registered_obj )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")
Re-Store from DB (optional)
In [ ]:
session.expunge_all()
del portf_registered_obj

for tsObj in session.query(PortfolioRegisterItem):  
    print(tsObj.name)
    if  tsObj.name  == "Portfolio Inv. Manager for US-Indexes - Montly-Rebalance TS" :
        break

portf_registered_obj = tsObj
print(portf_registered_obj.id, portf_registered_obj.name)
Execute Backtest
In [200]:
tsExecuteEngine = BacktestExecution( \
                    name = "Backtest for Portfolio I",
                    timePeriod = DatasetDef(datasetType = DatasetType.Testing,
                                            strBegDate = "2012-01-01", 
                                            strEndDate = "2015-12-31" ),
                    trade_asset_registered_item = portf_registered_obj )
In [ ]:
tsExecuteEngine.evaluate()
Backtest Metrics
Execution & Investment Metrics
In [202]:
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
        'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']]
Out[202]:
TA_Reg_Name Is_Portfolio Num_Trades_Completed Init_Capital Final_Capital Cum_Return Backtest_Status
0 Portfolio Inv. Manager for US-Indexes - Montly... Yes 684 54000000.0 5.421659e+07 0.004011 Completed
1 ts_sma_1_^DJI No 13 2250000.0 2.255893e+06 0.002619 Completed
2 ts_sma_2_^DJI No 26 2250000.0 2.255893e+06 0.002619 Completed
3 ts_sma_3_^DJI No 26 2250000.0 2.255893e+06 0.002619 Completed
4 ts_sma_4_^DJI No 24 2250000.0 2.293478e+06 0.019324 Completed
5 ts_sma_5_^DJI No 19 2250000.0 2.255893e+06 0.002619 Completed
6 ts_sma_6_^DJI No 34 2250000.0 2.255893e+06 0.002619 Completed
7 ts_sma_7_^DJI No 34 2250000.0 2.255893e+06 0.002619 Completed
8 all_^DJI No 53 2250000.0 2.293478e+06 0.019324 Completed
9 ts_sma_1_^IXIC No 11 2250000.0 2.255893e+06 0.002619 Completed
10 ts_sma_2_^IXIC No 23 2250000.0 2.255893e+06 0.002619 Completed
11 ts_sma_3_^IXIC No 23 2250000.0 2.255893e+06 0.002619 Completed
12 ts_sma_4_^IXIC No 16 2250000.0 2.255893e+06 0.002619 Completed
13 ts_sma_5_^IXIC No 13 2250000.0 2.255893e+06 0.002619 Completed
14 ts_sma_6_^IXIC No 36 2250000.0 2.255893e+06 0.002619 Completed
15 ts_sma_7_^IXIC No 36 2250000.0 2.255893e+06 0.002619 Completed
16 all_^IXIC No 57 2250000.0 2.255893e+06 0.002619 Completed
17 ts_sma_1_^GSPC No 11 2250000.0 2.255893e+06 0.002619 Completed
18 ts_sma_2_^GSPC No 32 2250000.0 2.255893e+06 0.002619 Completed
19 ts_sma_3_^GSPC No 32 2250000.0 2.255893e+06 0.002619 Completed
20 ts_sma_4_^GSPC No 22 2250000.0 2.255893e+06 0.002619 Completed
21 ts_sma_5_^GSPC No 17 2250000.0 2.255893e+06 0.002619 Completed
22 ts_sma_6_^GSPC No 36 2250000.0 2.255893e+06 0.002619 Completed
23 ts_sma_7_^GSPC No 36 2250000.0 2.255893e+06 0.002619 Completed
24 all_^GSPC No 54 2250000.0 2.255893e+06 0.002619 Completed
Performance Metrics
In [203]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ]
Out[203]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
0 Portfolio Inv. Manager for US-Indexes - Montly... Yes 2012-01-04 2015-12-31 0.71 0.0 0.0 0.04 -0.15 0.02 -0.02
1 ts_sma_1_^DJI No ts_sma_1 ^DJI 2012-01-04 2015-12-31 0.22 0.0 0.0 0.04 -0.15 0.06 -0.03
2 ts_sma_2_^DJI No ts_sma_2 ^DJI 2012-01-04 2015-12-31 0.28 0.0 0.0 0.05 -0.15 0.04 -0.03
3 ts_sma_3_^DJI No ts_sma_3 ^DJI 2012-01-04 2015-12-31 0.27 0.0 0.0 0.04 -0.15 0.04 -0.03
4 ts_sma_4_^DJI No ts_sma_4 ^DJI 2012-01-04 2015-12-31 0.31 0.02 0.0 0.1 -0.16 0.04 -0.03
5 ts_sma_5_^DJI No ts_sma_5 ^DJI 2012-01-04 2015-12-31 0.27 0.0 0.0 0.05 -0.15 0.04 -0.03
6 ts_sma_6_^DJI No ts_sma_6 ^DJI 2012-01-04 2015-12-31 0.3 0.0 0.0 0.05 -0.17 0.05 -0.05
7 ts_sma_7_^DJI No ts_sma_7 ^DJI 2012-01-04 2015-12-31 0.3 0.0 0.0 0.05 -0.16 0.04 -0.05
8 all_^DJI No all ^DJI 2012-01-04 2015-12-31 0.51 0.02 0.0 0.1 -0.15 0.06 -0.03
9 ts_sma_1_^IXIC No ts_sma_1 ^IXIC 2012-01-04 2015-12-31 0.21 0.0 0.0 0.05 -0.19 0.06 -0.04
10 ts_sma_2_^IXIC No ts_sma_2 ^IXIC 2012-01-04 2015-12-31 0.25 0.0 0.0 0.05 -0.2 0.04 -0.04
11 ts_sma_3_^IXIC No ts_sma_3 ^IXIC 2012-01-04 2015-12-31 0.24 0.0 0.0 0.05 -0.21 0.05 -0.04
12 ts_sma_4_^IXIC No ts_sma_4 ^IXIC 2012-01-04 2015-12-31 0.2 0.0 0.0 0.05 -0.17 0.05 -0.03
13 ts_sma_5_^IXIC No ts_sma_5 ^IXIC 2012-01-04 2015-12-31 0.19 0.0 0.0 0.05 -0.15 0.06 -0.03
14 ts_sma_6_^IXIC No ts_sma_6 ^IXIC 2012-01-04 2015-12-31 0.32 0.0 0.0 0.06 -0.19 0.04 -0.05
15 ts_sma_7_^IXIC No ts_sma_7 ^IXIC 2012-01-04 2015-12-31 0.3 0.0 0.0 0.05 -0.19 0.04 -0.05
16 all_^IXIC No all ^IXIC 2012-01-04 2015-12-31 0.47 0.0 0.0 0.07 -0.22 0.05 -0.04
17 ts_sma_1_^GSPC No ts_sma_1 ^GSPC 2012-01-04 2015-12-31 0.2 0.0 0.0 0.04 -0.17 0.06 -0.03
18 ts_sma_2_^GSPC No ts_sma_2 ^GSPC 2012-01-04 2015-12-31 0.29 0.0 0.0 0.05 -0.17 0.05 -0.05
19 ts_sma_3_^GSPC No ts_sma_3 ^GSPC 2012-01-04 2015-12-31 0.28 0.0 0.0 0.05 -0.16 0.04 -0.05
20 ts_sma_4_^GSPC No ts_sma_4 ^GSPC 2012-01-04 2015-12-31 0.27 0.0 0.0 0.05 -0.16 0.04 -0.03
21 ts_sma_5_^GSPC No ts_sma_5 ^GSPC 2012-01-04 2015-12-31 0.22 0.0 0.0 0.04 -0.18 0.03 -0.03
22 ts_sma_6_^GSPC No ts_sma_6 ^GSPC 2012-01-04 2015-12-31 0.3 0.0 0.0 0.05 -0.2 0.04 -0.06
23 ts_sma_7_^GSPC No ts_sma_7 ^GSPC 2012-01-04 2015-12-31 0.28 0.0 0.0 0.05 -0.2 0.05 -0.06
24 all_^GSPC No all ^GSPC 2012-01-04 2015-12-31 0.45 0.0 0.0 0.05 -0.17 0.05 -0.03
In [ ]:
tsExecuteEngine.getSummaryMetrics().T.head(60)
Persist Backtest to DB (optional )
In [ ]:
session.add( tsExecuteEngine )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst)
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")

Portfolio J

Portfolio J: Trade Strategies with different Market Data Sources (Quandal, YahooFinance, User-Defined DataFrame)

- Futures data is sourced from Quandal (Cotton, Soy Beans, and S&P 500 futures)

- US Equity indexes from Yahoo-Finance

- Leverage ETFs TQQQ and SQQQ from the user-defined DataFrame

- Multiple SMA Models, and LSTM, GRU, MACD, and RSI Models defined to use with each trading asset

- Additionally, there is a composite trade strategy for all Futures, and one composite trade
  strategy for the US Index equities

- Buy-and-Hold strategies for each trade asset for comparison

Backtest:

1. Type: regular

2. AI Models Fit Date Ranges
    1. Training Period: 
        1. Begin Date = 2001-01-01 
        2. End Date   = 2006-12-31  
    2. Validation Period: 
        1. Begin Date = 2007-01-01 
        2. End Date   = 2008-06-30 

3. Test Period: 
    1. Begin Date = 2009-01-01 
    2. End Date   = 2009-12-31         
Trade Assets - Yahoo-Finance
In [231]:
portfolio_trade_assets   = [ "^DJI", "^IXIC", "^GSPC" ]
Market Data Manager - Yahoo-Finance
In [232]:
dirPathMarketData = '/Users/gustavozambrana/Google Drive/Python/Projects/Trade_Engine/Data/US_Market_Indixes'

supportedTradeAssets   = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str           = "2000-01-01"
end_date_str           = None

ts_marketdat_mng_yf = TradeStrategyMarketDataMng(\
        marketDataProviderName = "yahoofinance",
        supportedTradeAssets   = supportedTradeAssets,
        stock_price_col_name   = "Adj Close",
        fileNameMarketData     = "US_Indixes_And_ETFs_MrkData",
        dirPathMarketData      = dirPathMarketData,
        beg_date_str           = beg_date_str,
        end_date_str           = end_date_str,
        interval               = "1d"  ) 
2021-10-28 22:14:56,355 [INFO] root: Found previous Market data previously loaded to specified file and dir.
In [233]:
ts_marketdat_mng_yf.marketDataObj.getDataFrame()
Out[233]:
Index Adj Close Close High Low Open Volume
Date
2000-01-03 ^DJI 11357.509766 11357.509766 11522.009766 11305.690430 11501.849609 169750000
2000-01-03 ^GSPC 1455.219971 1455.219971 1478.000000 1438.359985 1469.250000 931800000
2000-01-03 ^IXIC 4131.149902 4131.149902 4192.189941 3989.709961 4186.189941 1510070000
2000-01-04 ^DJI 10997.929688 10997.929688 11350.059570 10986.450195 11349.750000 178420000
2000-01-04 ^GSPC 1399.420044 1399.420044 1455.219971 1397.430054 1455.219971 1009000000
... ... ... ... ... ... ... ...
2021-09-20 TQQQ 133.490005 133.490005 137.460007 128.000000 135.419998 60721113
2021-09-20 UDOW 69.760002 69.760002 71.459999 67.519997 70.220001 6439708
2021-09-20 ^DJI 33970.468750 33970.468750 34459.718750 33613.031250 34459.718750 441645657
2021-09-20 ^GSPC 4357.729980 4357.729980 4402.950195 4305.910156 4402.950195 2598257000
2021-09-20 ^IXIC 14713.903320 14713.903320 14841.815430 14530.073242 14758.099609 4350941000

34549 rows × 7 columns

Trade Assets - From User-Defined Pandas DataFrame

User can provide their own market data via a Pandas DataFrame

Requirements:

1. DataFrame Index : must be called "Date", and be of datetime format
2. Index column : All data associated with a given trade asset. Same exact format as the 
   yahoofinance above
3. The rest of the columns in the dataframe can be named anything. However, it is recommended
   they used standard names as the ones in YahooFinance above; this will make all built-in 
   AI and Technical Analysis Models available.
4. Note, interval, supportedTradeAssets are constraint and not enforced; the data that is passed
   in the dataframe is what is supported.
In [234]:
ts_marketdat_mng_df = TradeStrategyMarketDataMng(\
        marketDataProviderName = "dataframe",
        marketDataDF           =  ts_marketdat_mng_yf.marketDataObj.getDataFrame(),                     
        supportedTradeAssets   = supportedTradeAssets,
        stock_price_col_name   = "Adj Close",
        fileNameMarketData     = "US_Indixes_And_ETFs_MrkData_DF",
        dirPathMarketData      = dirPathMarketData,
        beg_date_str           = beg_date_str,
        end_date_str           = end_date_str,
        interval               = "1d"  ) 
2021-10-28 22:15:09,740 [INFO] root: Found previous Market data previously loaded to specified file and dir.
In [235]:
ts_marketdat_mng_df.marketDataObj.getDataFrame()
Out[235]:
Index Adj Close Close High Low Open Volume
Date
2000-01-03 ^DJI 11357.509766 11357.509766 11522.009766 11305.690430 11501.849609 169750000
2000-01-03 ^GSPC 1455.219971 1455.219971 1478.000000 1438.359985 1469.250000 931800000
2000-01-03 ^IXIC 4131.149902 4131.149902 4192.189941 3989.709961 4186.189941 1510070000
2000-01-04 ^DJI 10997.929688 10997.929688 11350.059570 10986.450195 11349.750000 178420000
2000-01-04 ^GSPC 1399.420044 1399.420044 1455.219971 1397.430054 1455.219971 1009000000
... ... ... ... ... ... ... ...
2021-09-20 TQQQ 133.490005 133.490005 137.460007 128.000000 135.419998 60721113
2021-09-20 UDOW 69.760002 69.760002 71.459999 67.519997 70.220001 6439708
2021-09-20 ^DJI 33970.468750 33970.468750 34459.718750 33613.031250 34459.718750 441645657
2021-09-20 ^GSPC 4357.729980 4357.729980 4402.950195 4305.910156 4402.950195 2598257000
2021-09-20 ^IXIC 14713.903320 14713.903320 14841.815430 14530.073242 14758.099609 4350941000

34549 rows × 7 columns

Trade Assets - Quandal

Download the following data from Quandal:

  1. CHRIS/CME_S2
  2. CHRIS/ICE_CT1
  3. CHRIS/CME_SP1

    Where CHRIS is the Quandal Data Provider, and the name after the / is the Futures symbol.

    The format of the JSON to download from Quandal is:

    { quandal-path :

       [ description of data, 
         [ columns to extract from the returned Quandal DataFrame ], 
         { "Quandal_Column" : "Rename Quandal Column" } 
       ]
    

    }

Note:

1. The nested dictionary to rename the original downloaded Quandal data, it is provided since Quandal does
   not have standard output column names.  
       - Futures data from different data sources might have different returned column names for the same
         state, that is "Close" vs. "close", etc.
       - For sharing the same market data manager object it is recommended to rename the columns to have 
         standard names, and match the ones provided by Yahoo Finance

2. Yahoo Finance returns standard equity column names

3. All implemented AI and Technical Models used standard column names (same as Yahoo Finance)
   Columns: Adj Close, Close, Open, High, Low, Volume
   Index: Datetime

4. In order to use the implemented models the Quandal Market Data or any Custom Market Data must have
   similar named columns, or the user can implement his own models and use whatever column names he/she
   prefers.

5. In this example, the Quandal data source does not provide all standard column names, only open,
   which is re-named to 'Adj Close'.  Therefore only some of the built models will be available,
   as they required High, Low, such as Bollinger Bands
In [236]:
indexQuantCodeMap = { 
       "CHRIS/CME_S2"  : ["SoyBeans", ["Open", "Volume"],  { "Open" : "Adj Close" } ],
       "CHRIS/ICE_CT1" : ["Cotton",   ["Open", "Volume"],  { "Open" : "Adj Close" } ],
       "CHRIS/CME_SP1" : ["S&P_500",  ["Open", "Volume"],  { "Open" : "Adj Close" } ]  }
Market Data Manager - Quandal
In [237]:
dirPathMarketDataQuandl = '/Users/gustavozambrana/Google Drive/Python/Projects/Trade_Engine/Data/TSMarketDat'

beg_date_for_feature_creation = "2000-10-01"
beg_date_str                  = "2001-01-01"
end_date_str                  = "2010-12-31"

q_stock_index_list = list ( indexQuantCodeMap.keys()  )

ts_marketdat_mng_quandal = TradeStrategyMarketDataMng(\
        marketDataProviderName = "quandl",
        supportedTradeAssets   = q_stock_index_list,   
        stock_price_col_name   = "Adj Close",
        fileNameMarketData     = "Quandl_Test_1_PorfolioRegisterItem_Portf_J",
        dirPathMarketData      = dirPathMarketDataQuandl,
        beg_date_str           = beg_date_for_feature_creation,
        end_date_str           = end_date_str,
        interval               = "1d" ,
        updateDataPassEndDate  = False,
        forceCreateMarketData  = False,
        indexQuantCodeMap      = indexQuantCodeMap     # required for quandl market data provider, defined above
        ) 
2021-10-28 22:15:20,626 [INFO] root: Found previous Market data previously loaded to specified file and dir.
In [238]:
ts_marketdat_mng_quandal.marketDataObj.getDataFrame()
Out[238]:
Index Index_Name Provider Adj Close Volume
Date
2000-10-02 CHRIS/CME_S2 SoyBeans Quandl 498.00 4183.0
2000-10-02 CHRIS/CME_SP1 S&P_500 Quandl 1460.50 61706.0
2000-10-02 CHRIS/ICE_CT1 Cotton Quandl 62.17 40.0
2000-10-03 CHRIS/CME_S2 SoyBeans Quandl 499.00 4324.0
2000-10-03 CHRIS/CME_SP1 S&P_500 Quandl 1463.00 72987.0
... ... ... ... ... ...
2010-12-30 CHRIS/CME_SP1 S&P_500 Quandl 1255.70 5876.0
2010-12-30 CHRIS/ICE_CT1 Cotton Quandl 140.00 10309.0
2010-12-31 CHRIS/CME_S2 SoyBeans Quandl 1387.00 60405.0
2010-12-31 CHRIS/CME_SP1 S&P_500 Quandl 1254.50 10650.0
2010-12-31 CHRIS/ICE_CT1 Cotton Quandl 144.00 5421.0

7540 rows × 5 columns

Pipeline Data Managers

For AI models, shared pipeline

For Yahoo-Finance Mkt Data
In [239]:
ts_model_pipline_mng_yf = TradeStrategyModelPipelineDataMng(\
                            tsMarketDataMng    = ts_marketdat_mng_yf,
                            package            = "trade_engine.model.ai.WaveNet_RNN_AI_PipelineBuilder",
                            model_class_name   = "WaveNet_RNN_AI_PipelineBuilder",
                            fileNameMarketData = "WaveNet_RNN_AI_Pipeline_Data_Portf_YF",
                            forceCreatePipelineData = True,
                            dirPathMarketData  = dirPathMarketData )
For User-Defined DataFrame Mkt Data
In [240]:
ts_model_pipline_mng_df = TradeStrategyModelPipelineDataMng(\
                            tsMarketDataMng    = ts_marketdat_mng_df,
                            package            = "trade_engine.model.ai.WaveNet_RNN_AI_PipelineBuilder",
                            model_class_name   = "WaveNet_RNN_AI_PipelineBuilder",
                            fileNameMarketData = "WaveNet_RNN_AI_Pipeline_Data_Portf_DF",
                            forceCreatePipelineData = True,
                            dirPathMarketData  = dirPathMarketData )
For Quandal Mkt Data

Note:

- The rnn pipeline builder is built explicitily and the columns to use in the AI RNN based models defined.
- The Quandal data source in the example only has data for the 'Adj Close', 'Volume', the default is 
  to assume all standard columns for equities returned by Yahoo Finance
In [241]:
ai_rnn_pipeline_builder = WaveNet_RNN_AI_PipelineBuilder(\
                                        stock_index_col = 'Index',
                                        pipeline_cols   = ['Adj Close', 'Volume' ],
                                        y_feature_col   =  'Adj Close' )

ts_model_pipline_mng_quandal = TradeStrategyModelPipelineDataMng(\
                            tsMarketDataMng    = ts_marketdat_mng_quandal,
                            modelPipelineBuilder = ai_rnn_pipeline_builder,
                            fileNameMarketData = "WaveNet_RNN_AI_Pipeline_Data_Portf_Quandal",
                            forceCreatePipelineData = True,
                            dirPathMarketData  = dirPathMarketData )
Simulation Broker
In [242]:
brokerTradingObj = SimBrokerTrading()
Trade Strategies, Trade Investment Manager, and Trade Asset Register Items
Define Multiple SMA Models, LSTM, GRU, MACD, and RSI Models
In [243]:
taRegisterItems = [ ]
tsConfDat = TradeStrategyConfigData()

# Set Config

tsConfDat.tsSetConfig(\
    ts_set_conf_dict = 
           { 'set_actions_conf' : 
                      { "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
                        "exit"  : { 'votingPolicy' : 1, 
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1 } 
                      }
           } )
           
# TS #1

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_1",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 20, 'win_slow' : 100 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : True },
                                  'exit_policy_args'   : { 'lastn_match' : 2 } },
                             },
                    }  )

# TS #2

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_2",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 10, 'win_slow' : 50 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : True },
                                  'exit_policy_args'   : { 'lastn_match' : 2 } },
                             },
                    }  )

# TS #3

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_3",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 10, 'win_slow' : 50 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : True },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },
                             },
                    }  )

# TS #4

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_4",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 15, 'win_slow' : 60 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : True },
                                  'exit_policy_args'   : { 'lastn_match' : 2 } },
                             },
                    }  )

# TS #5

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_5",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 15, 'win_slow' : 75 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : True },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },
                             },
                    }  )

# TS #6

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_6",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 7, 'win_slow' : 35 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : True },
                                  'exit_policy_args'   : { 'lastn_match' : 2 } },
                             },
                    }  )

# TS #7

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_7",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 7, 'win_slow' : 35 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : True },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },
                             },
                    }  )

# TS #8

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_gru", 
    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "gru",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'         : 20 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 1, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },

                               "stop_lost" :
                                    { 'model'    : "fix_perc",
                                      'type'     : "ta",
                                      'obj_args' : { 'long_stop_los_per' : 5, 'short_stop_los_per'    : 5 }  } 
                             },
                    }  )

# TS #9

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_lstm", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'         : 50,   'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn'   : True,
                                                 'epochs'          : 20 }  
                                }
                            } }  )

# TS #10

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_macd",    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "macd",
                                  'type'     : "ta",
                                  'obj_args' : { 'window_slow' : 26, 'window_fast' : 12, 'window_sign' : 9,
                                                 'enter_long_macd_diff'  : 0.5 , 'exi_long_macd_diff' : 0.5,
                                                 'enter_short_macd_diff' : -0.5, 'exi_short_macd_diff' : -0.5  },
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 },
                                },
                            }  } )
# TS #11

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_rsi",    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "rsi",
                                  'type'     : "ta",
                                  'obj_args' : { 'rsi_enter_long'  : 30.0,  'rsi_exit_long'  : 30.0, 
                                                 'rsi_enter_short' : 70.0,  'rsi_exit_short' : 70.0 },
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 },
                                },
                            }  } )
Equity Trade Strategies (using Yahoo Finance Market Data)
In [244]:
taRegisterItems = [ ]
tsActionGen = TradeStrategyActionGenerator()

for trade_asset in portfolio_trade_assets :
    
    num_ts = len(tsConfDat.name_list) + 1  # adding the composite  trade strategy
    
    for i in range( num_ts ) :

        if i <= num_ts - 2:
            # *** Trade Strategy 

            actionDatItem  = tsConfDat.getTSConfigDataForItem(item_num = i )
            ts_unique_name = actionDatItem.name_list[0]
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng_yf, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = actionDatItem,
                                                     pipelineMng       = ts_model_pipline_mng_yf )
        else :
            # Composite Trade Strategy 
            
            ts_unique_name = "all"            
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng_yf, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = tsConfDat,
                                                     pipelineMng       = ts_model_pipline_mng_yf )

        ts_model = TradeStrategyBaseModelPersist(\
                        trade_asset               = trade_asset,
                        ts_marketdat_mng          = ts_marketdat_mng_yf,
                        ts_enter                  = trade_enter_set,
                        ts_exit                   = trade_exit_set,                       
                        model_type                = ts_unique_name,
                        model_version             = "1.0",
                        market_data_period        = MarketDataPeriod.Day,
                    ) 

        # *** Trade Strategy Investment Manager 

        taInvMng = TradingAssetInvMngBase(\
                                        trade_asset                = trade_asset,
                                        minPeriodsBetweenTrades    = 1,
                                        initInvestment             = 1000000.0, 
                                        capPercentToInvestPerTrade = 100.0,
                                        minInvestPercent           = 5.0,
                                        min_account_balance        = 1000.0 )

        # *** Trade Register Item
        # *** This object has all configuration defined to execute a given trade strategy,
        # *** It can be executed individually in backtest or as part of a portfolio

        ta_registered_item = TradingAssetRegisterItem(\
                trade_name                    = "{0}_{1}".format(ts_unique_name, trade_asset), 
                ts_model                      = ts_model,
                tradingExecutionType          = TradingAssetExecutionType.Simulation,
                tradingBrokerObj              = brokerTradingObj,
                tradingAssetInvMngObj         = taInvMng )  

        taRegisterItems.append(ta_registered_item)
Futures Trade Strategies (using Quandal Futures data)
In [245]:
tsActionGen = TradeStrategyActionGenerator()

for trade_asset in q_stock_index_list :
    
    num_ts = len(tsConfDat.name_list) + 1  # adding the composite trade strategy
    
    for i in range( num_ts ) :

        if i <= num_ts - 2:
            # *** Trade Strategy 

            actionDatItem  = tsConfDat.getTSConfigDataForItem(item_num = i )
            ts_unique_name = actionDatItem.name_list[0]
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng_quandal, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = actionDatItem,
                                                     pipelineMng       = ts_model_pipline_mng_quandal )
        else :
            # Composite Trade Strategy 
            
            ts_unique_name = "all"            
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng_quandal, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = tsConfDat,
                                                     pipelineMng       = ts_model_pipline_mng_quandal )

        ts_model = TradeStrategyBaseModelPersist(\
                        trade_asset               = trade_asset,
                        ts_marketdat_mng          = ts_marketdat_mng_quandal,
                        ts_enter                  = trade_enter_set,
                        ts_exit                   = trade_exit_set,                       
                        model_type                = ts_unique_name,
                        model_version             = "1.0",
                        market_data_period        = MarketDataPeriod.Day,
                    ) 

        # *** Trade Strategy Investment Manager 

        taInvMng = TradingAssetInvMngBase(\
                                        trade_asset                = trade_asset,
                                        minPeriodsBetweenTrades    = 1,
                                        initInvestment             = 1000000.0, 
                                        capPercentToInvestPerTrade = 100.0,
                                        minInvestPercent           = 5.0,
                                        min_account_balance        = 1000.0 )

        # *** Trade Register Item
        # *** This object has all configuration defined to execute a given trade strategy,
        # *** It can be executed individually in backtest or as part of a portfolio

        ta_registered_item = TradingAssetRegisterItem(\
                trade_name                    = "{0}_{1}".format(ts_unique_name, trade_asset), 
                ts_model                      = ts_model,
                tradingExecutionType          = TradingAssetExecutionType.Simulation,
                tradingBrokerObj              = brokerTradingObj,
                tradingAssetInvMngObj         = taInvMng )  

        taRegisterItems.append(ta_registered_item)
Trade Strategies (using User-Defined Pandas DataFrame)
In [246]:
tsActionGen = TradeStrategyActionGenerator()

for trade_asset in [ '^DJI', '^IXIC' ] :
    
    num_ts = len(tsConfDat.name_list) + 1  # adding the composite trade strategy
    
    for i in range( num_ts ) :

        if i <= num_ts - 2:
            # *** Trade Strategy 

            actionDatItem  = tsConfDat.getTSConfigDataForItem(item_num = i )
            ts_unique_name = actionDatItem.name_list[0]
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng_df, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = actionDatItem,
                                                     pipelineMng       = ts_model_pipline_mng_df )
        else :
            # Composite Trade Strategy 
            
            ts_unique_name = "all"            
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng_df, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = tsConfDat,
                                                     pipelineMng       = ts_model_pipline_mng_df )

        ts_model = TradeStrategyBaseModelPersist(\
                        trade_asset               = trade_asset,
                        ts_marketdat_mng          = ts_marketdat_mng_df,
                        ts_enter                  = trade_enter_set,
                        ts_exit                   = trade_exit_set,                       
                        model_type                = ts_unique_name,
                        model_version             = "1.0",
                        market_data_period        = MarketDataPeriod.Day,
                    ) 

        # *** Trade Strategy Investment Manager 

        taInvMng = TradingAssetInvMngBase(\
                                        trade_asset                = trade_asset,
                                        minPeriodsBetweenTrades    = 1,
                                        initInvestment             = 1000000.0, 
                                        capPercentToInvestPerTrade = 100.0,
                                        minInvestPercent           = 5.0,
                                        min_account_balance        = 1000.0 )

        # *** Trade Register Item
        # *** This object has all configuration defined to execute a given trade strategy,
        # *** It can be executed individually in backtest or as part of a portfolio

        ta_registered_item = TradingAssetRegisterItem(\
                trade_name                    = "{0}_{1}".format(ts_unique_name, trade_asset), 
                ts_model                      = ts_model,
                tradingExecutionType          = TradingAssetExecutionType.Simulation,
                tradingBrokerObj              = brokerTradingObj,
                tradingAssetInvMngObj         = taInvMng )  

        taRegisterItems.append(ta_registered_item)
In [247]:
print("Number of configured Trade Asset Register Items: ", len(taRegisterItems) )
Number of configured Trade Asset Register Items:  96
Portfolio Investment Manager
In [248]:
# *** Porttfolio Investment Manager across all individual trade strategies investment managers
# *** Role: 
# ***    1) Managed investment funds across n number of trade strategies
# ***    2) Rebalance portfolio periodically or never
# ***    3) Portfolio Policy Weights 
# ***          equal weights (default)
# ***          MinimumVariance
# ***          User defined 
# ***    4) Track Portfolio level returns and metrics
# ***          Individual Trade Strategies return and metrics tracked through their 
# ***          investment managers
# ***          Portfolio funds are split across each trade strategy investment manager based on the
# ***          portfolio weights

portfInvMng = PortfolioInvMng(\
                  name                       = "Portfolio Inv. Manager, Quandal, YahooFinance, DF",
                  initInvestment             = 2000000.0 * ( len(taRegisterItems) + 3),  # 200K/trade-strag
                  portfRebalanceFreq         = PortfolioRebalanceFrequency.Never,
                  portfRebalancePeriods      = 1,
                  minInvestPercent           = 5.0,
                  min_account_balance        = 1000.0,     
                  minPeriodsBetweenTrades    = 1,
                  capPercentToInvestPerTrade = 100.0 )
Trade Register Items Portfolio
In [249]:
# *** Set of Trade Register Items
#
# Configuration Summary:
#    - Each set has 1 to n trade register items as previously described 
#    - Optionally add long only trade strategies for all unique trade assets in the
#      portfolio 
#           - (Dow, Nasdaq, and S&P 500 for this portfolio) in this example
#           - Might be useful for bench marking trade strategies
#    - Each set has one Investment Portfolio Manager
#       - portfolio funds allocated per portfolio policy rules and re-balanced (if defined), 
#         across all trade strategies


portf_registered_obj = PortfolioRegisterItem(\
                        name                 = "Portfolio Inv. Manager, Quandal, YahooFinance, DF",
                        taRegisterItems      = taRegisterItems,
                        portfolioInvMngObj   = portfInvMng,
                        tradingExecutionType = TradingAssetExecutionType.Simulation,
                        add_long_only_ts     = True )
2021-10-28 22:16:33,747 [INFO] root: *** Adding long only trade strategies for : {'CHRIS/CME_SP1', 'CHRIS/ICE_CT1', '^GSPC', '^DJI', '^IXIC', 'CHRIS/CME_S2'}
Persist to DB (optional)
In [ ]:
session.add( portf_registered_obj )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")
Re-Store from DB (optional)
In [ ]:
session.expunge_all()
del portf_registered_obj

for tsObj in session.query(PortfolioRegisterItem):  
    print(tsObj.name)
    if  tsObj.name  == "Portfolio Inv. Manager, Quandal, YahooFinance, DF" :
        break

portf_registered_obj = tsObj
print(portf_registered_obj.id, portf_registered_obj.name)
Training, Validation and Test Periods for Backtest

In Order to backtest a trade strategy or portfolio that has AI models, the following data is required:

  1. Training Date Range

    1. Date range that will be used to train the AI models in the backtest
  2. Validation Date Range

    1. Date range that twill be used to validate the AI models, should not overlapped with the training date range
  3. Test Period Date Range

    1. This is the out-sample date range, which corresponds to the date range of the backtest

Date Ranges are defined with a DatasetDef object, and have the following parameters:

  1. strBegDateAIModels : Date to begin training or validation of an AI model
  2. strBegDate : Date to begin the backtest
  3. strEndDate : Date to end training, validation and Backtest

Note:

  1. The param strBegDateAIModels can be defined as the same date as strBegDate, that is the default, if not defined.
  2. The critical aspect of using this parameter is in the backtest. Some AI Models, such as time series, others using moving averages over many periods, create params with no predicting data for those initial dates. Thus, in order to ensure the backtest starts on the actual date specified, the strBegDateAIModels should be defined as an earlier date, and it should not overlapped with the validation period end-date to avoid any chance of bias by picking at the validation data.
In [250]:
training_period = DatasetDef(datasetType = DatasetType.Training,
                             strBegDateAIModels = "2000-10-05",
                             strBegDate         = "2001-01-01",
                             strEndDate         = "2006-12-31" )

validation_period = DatasetDef(datasetType = DatasetType.Validation,
                               strBegDateAIModels = "2006-07-01",
                               strBegDate         = "2007-01-01",
                               strEndDate         = "2008-12-31" )

testing_period = DatasetDef(datasetType = DatasetType.Testing,
                               strBegDateAIModels = "2008-07-01",
                               strBegDate         = "2009-01-01",
                               strEndDate         = "2009-12-31" )

fit_datasets = FitDatasetsDef( trainingDataset    = training_period,
                               validationDataset  = validation_period )
Execute Backtest
In [251]:
tsExecuteEngine = BacktestExecution( \
                    name = "Backtest for Portfolio J",
                    timePeriod  = testing_period,
                    fitDatasets = fit_datasets,
                    trade_asset_registered_item = portf_registered_obj )
In [ ]:
tsExecuteEngine.evaluate()
Backtest Metrics
Execution & Investment Metrics
In [253]:
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
        'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
        query('TA_Reg_Name.str.contains("CHRIS")', engine='python')
Out[253]:
TA_Reg_Name Is_Portfolio Num_Trades_Completed Init_Capital Final_Capital Cum_Return Backtest_Status
37 ts_sma_1_CHRIS/CME_S2 No 5 1.941176e+06 1.181225e+06 -0.391490 Completed
38 ts_sma_2_CHRIS/CME_S2 No 6 1.941176e+06 1.782112e+06 -0.081942 Completed
39 ts_sma_3_CHRIS/CME_S2 No 6 1.941176e+06 1.781919e+06 -0.082041 Completed
40 ts_sma_4_CHRIS/CME_S2 No 5 1.941176e+06 1.642411e+06 -0.153909 Completed
41 ts_sma_5_CHRIS/CME_S2 No 5 1.941176e+06 1.255283e+06 -0.353339 Completed
42 ts_sma_6_CHRIS/CME_S2 No 7 1.941176e+06 1.915940e+06 -0.013000 Completed
43 ts_sma_7_CHRIS/CME_S2 No 7 1.941176e+06 1.798736e+06 -0.073378 Completed
44 ts_gru_CHRIS/CME_S2 No 93 1.941176e+06 1.837204e+06 -0.053561 Completed
45 ts_lstm_CHRIS/CME_S2 No 64 1.941176e+06 1.910883e+06 -0.015605 Completed
46 ts_macd_CHRIS/CME_S2 No 22 1.941176e+06 1.931941e+06 -0.004757 Completed
47 ts_rsi_CHRIS/CME_S2 No 9 1.941176e+06 1.909357e+06 -0.016392 Completed
48 all_CHRIS/CME_S2 No 30 1.941176e+06 1.803234e+06 -0.071061 Completed
49 ts_sma_1_CHRIS/ICE_CT1 No 1 1.941176e+06 3.032058e+06 0.561969 Completed
50 ts_sma_2_CHRIS/ICE_CT1 No 7 1.941176e+06 1.411244e+06 -0.272995 Completed
51 ts_sma_3_CHRIS/ICE_CT1 No 7 1.941176e+06 1.654444e+06 -0.147711 Completed
52 ts_sma_4_CHRIS/ICE_CT1 No 5 1.941176e+06 2.200841e+06 0.133766 Completed
53 ts_sma_5_CHRIS/ICE_CT1 No 5 1.941176e+06 2.283220e+06 0.176204 Completed
54 ts_sma_6_CHRIS/ICE_CT1 No 6 1.941176e+06 1.759581e+06 -0.093549 Completed
55 ts_sma_7_CHRIS/ICE_CT1 No 6 1.941176e+06 2.119280e+06 0.091750 Completed
56 ts_gru_CHRIS/ICE_CT1 No 69 1.941176e+06 2.725994e+06 0.404300 Completed
57 ts_lstm_CHRIS/ICE_CT1 No 47 1.941176e+06 2.135238e+06 0.099971 Completed
58 ts_macd_CHRIS/ICE_CT1 No 24 1.941176e+06 1.695369e+06 -0.126628 Completed
59 ts_rsi_CHRIS/ICE_CT1 No 7 1.941176e+06 2.116962e+06 0.090556 Completed
60 all_CHRIS/ICE_CT1 No 22 1.941176e+06 2.342335e+06 0.206657 Completed
61 ts_sma_1_CHRIS/CME_SP1 No 1 1.941176e+06 2.600468e+06 0.339635 Completed
62 ts_sma_2_CHRIS/CME_SP1 No 5 1.941176e+06 2.261261e+06 0.164892 Completed
63 ts_sma_3_CHRIS/CME_SP1 No 5 1.941176e+06 2.147903e+06 0.106495 Completed
64 ts_sma_4_CHRIS/CME_SP1 No 3 1.941176e+06 2.358685e+06 0.215080 Completed
65 ts_sma_5_CHRIS/CME_SP1 No 1 1.941176e+06 2.597068e+06 0.337883 Completed
66 ts_sma_6_CHRIS/CME_SP1 No 6 1.941176e+06 2.278610e+06 0.173829 Completed
67 ts_sma_7_CHRIS/CME_SP1 No 6 1.941176e+06 2.224219e+06 0.145810 Completed
68 ts_gru_CHRIS/CME_SP1 No 65 1.941176e+06 2.049154e+06 0.055625 Completed
69 ts_lstm_CHRIS/CME_SP1 No 32 1.941176e+06 2.288071e+06 0.178703 Completed
70 ts_macd_CHRIS/CME_SP1 No 31 1.941176e+06 1.634286e+06 -0.158095 Completed
71 ts_rsi_CHRIS/CME_SP1 No 11 1.941176e+06 2.157958e+06 0.111675 Completed
72 all_CHRIS/CME_SP1 No 22 1.941176e+06 2.284183e+06 0.176700 Completed
97 Long-Only Trade Strategy for CHRIS/CME_SP1 No 1 1.941176e+06 2.422208e+06 0.247804 Completed
98 Long-Only Trade Strategy for CHRIS/ICE_CT1 No 1 1.941176e+06 2.975400e+06 0.532782 Completed
102 Long-Only Trade Strategy for CHRIS/CME_S2 No 1 1.941176e+06 2.101256e+06 0.082465 Completed
Performance Metrics
In [254]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ]
Out[254]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
0 Portfolio Inv. Manager, Quandal, YahooFinance, DF Yes 2009-01-05 2009-12-31 1.0 0.12 0.12 1.19 -0.04 0.02 -0.02
1 ts_sma_1_^DJI No ts_sma_1 ^DJI 2009-01-05 2009-12-31 0.68 0.28 0.28 1.83 -0.07 0.03 -0.03
2 ts_sma_2_^DJI No ts_sma_2 ^DJI 2009-01-05 2009-12-31 0.99 0.13 0.13 0.67 -0.15 0.05 -0.06
3 ts_sma_3_^DJI No ts_sma_3 ^DJI 2009-01-05 2009-12-31 0.98 0.18 0.18 0.86 -0.15 0.05 -0.06
4 ts_sma_4_^DJI No ts_sma_4 ^DJI 2009-01-05 2009-12-31 0.75 0.07 0.07 0.49 -0.18 0.03 -0.04
... ... ... ... ... ... ... ... ... ... ... ... ... ...
98 Long-Only Trade Strategy for CHRIS/ICE_CT1 No long CHRIS/ICE_CT1 2009-01-05 2009-12-31 1.0 0.53 0.54 1.47 -0.23 0.12 -0.07
99 Long-Only Trade Strategy for ^GSPC No long ^GSPC 2009-01-05 2009-12-31 1.0 0.2 0.2 0.8 -0.28 0.07 -0.05
100 Long-Only Trade Strategy for ^DJI No long ^DJI 2009-01-05 2009-12-31 1.0 0.15 0.16 0.72 -0.27 0.07 -0.05
101 Long-Only Trade Strategy for ^IXIC No long ^IXIC 2009-01-05 2009-12-31 1.0 0.39 0.4 1.32 -0.23 0.07 -0.06
102 Long-Only Trade Strategy for CHRIS/CME_S2 No long CHRIS/CME_S2 2009-01-05 2009-12-31 0.98 0.08 0.08 0.41 -0.25 0.06 -0.08

103 rows × 13 columns

In [ ]:
tsExecuteEngine.getSummaryMetrics().T.head(60)
Persist Backtest to DB (optional )
In [ ]:
session.add( tsExecuteEngine )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst)
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")
In [ ]:
 

WFA Backtest

A type of backtests that are designed to simulate fitting AI Models to different date ranges or to shift the date ranges for a backtest through time.

- Description :

- Re-fit the AI models that a given trade strategy depends on during a backtest

- Scenario:

- Given the following initial setting for a backtest:

    AI Models Fit Date Ranges
        1. Training Period: 
            1. Begin Date = 2001-01-01 
            2. End Date   = 2005-12-31  
        2. Validation Period: 
            1. Begin Date = 2006-01-01 
            2. End Date   = 2007-06-30   

    Test Period: 
        1. Begin Date = 2008-01-01 
        2. End Date   = 2008-12-31 

- Re-fit the models after the backtest has executed for a period (n days, n weeks, n months), by 
  either shifting the Training and Validation period or extending, that is anchoring the Training
  Period start date

Example 1

  • shifting Training and Validation periods
  • re-fit every three months
  • the AI Models will be trained and validate with the following date ranges:
    • Iteration 1:
      1. Training Period: 
          1. Begin Date = 2001-01-01 
          2. End Date   = 2005-12-31  
      2. Validation Period: 
          1. Begin Date = 2006-01-01 
          2. End Date   = 2007-06-30   
    • Iteration 2:
      1. Training Period: 
          1. Begin Date = 2001-04-01 
          2. End Date   = 2006-03-31  
      2. Validation Period: 
          1. Begin Date = 2006-04-01 
          2. End Date   = 2007-09-30    
      
      • Iteration n: ...
  • The backtest, for dates between 2008-04-01 and 2008-06-30, will use the updated re-fitted models
  • The re-fit process will continue throughout the backtest until the backtest ends.

Example 2

  • anchored Training Set
  • re-fit every three months
  • the AI Models will be trained and validate with the following date ranges:
    • Iteration 1:
      1. Training Period: 
          1. Begin Date = 2001-01-01 
          2. End Date   = 2005-12-31  
      2. Validation Period: 
          1. Begin Date = 2006-01-01 
          2. End Date   = 2007-06-30  
    • Iteration 2:
      1. Training Period: 
          1. Begin Date = 2001-01-01 
          2. End Date   = 2006-03-31  
      2. Validation Period: 
          1. Begin Date = 2006-04-01 
          2. End Date   = 2007-09-30 
    • Iteration n:
      ... 
  • The backtest, for dates between 2008-04-01 and 2008-06-30, will use the updated re-fitted models
  • The re-fit process will continue throughout the backtest

WFA-Backtest 1

Description:

  • Portfolio has a subset of the trade strategies in Portfolio D
    • Smaller subset of AI models to reduce execution duration
  • Re-fit AI trading models every 4 months. For this example, there will be a total of three times the AI models are fitted, that is:
    1. Before WFA Backtest starts
    2. May 1
    3. September 1
  • Training-set is not anchored

Backtest:

1. Type: WFA Backtest
2. AI Models Fit Date Ranges
    1. Training Period: 
        1. Begin Date = 2000-01-01 
        2. End Date   = 2005-12-31  
    2. Validation Period: 
        1. Begin Date = 2006-01-01 
        2. End Date   = 2007-12-31   
4. Test Period: 
    1. Begin Date = 2008-01-01 
    2. End Date   = 2008-12-31         

Portfolio Trade Assets

In [255]:
portfolio_trade_assets   = [ "^DJI", "^IXIC", "^GSPC" ]

Market Data Manager

In [256]:
dirPathMarketData = '/Users/gustavozambrana/Google Drive/Python/Projects/Trade_Engine/Data/US_Market_Indixes'

supportedTradeAssets   = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str           = "1980-01-01"
end_date_str           = None

ts_marketdat_mng = TradeStrategyMarketDataMng(\
        marketDataProviderName = "yahoofinance",
        supportedTradeAssets   = supportedTradeAssets,
        stock_price_col_name   = "Adj Close",
        fileNameMarketData     = "US_Indixes_And_ETFs_MrkData_From_1980",
        dirPathMarketData      = dirPathMarketData,
        beg_date_str           = beg_date_str,
        end_date_str           = end_date_str,
        interval               = "1d"  ) 
******* Initial Market Data Download ******* 

Downloading: ^DJI interval = 1d  beg_date = 1980-01-01  end_date = None
[*********************100%***********************]  1 of 1 completed
Downloading: ^IXIC interval = 1d  beg_date = 1980-01-01  end_date = None
[*********************100%***********************]  1 of 1 completed
Downloading: ^GSPC interval = 1d  beg_date = 1980-01-01  end_date = None
[*********************100%***********************]  1 of 1 completed
Downloading: UDOW interval = 1d  beg_date = 1980-01-01  end_date = None
[*********************100%***********************]  1 of 1 completed
Downloading: SDOW interval = 1d  beg_date = 1980-01-01  end_date = None
[*********************100%***********************]  1 of 1 completed
Downloading: SPXL interval = 1d  beg_date = 1980-01-01  end_date = None
[*********************100%***********************]  1 of 1 completed
Downloading: SPXS interval = 1d  beg_date = 1980-01-01  end_date = None
[*********************100%***********************]  1 of 1 completed
Downloading: TQQQ interval = 1d  beg_date = 1980-01-01  end_date = None
[*********************100%***********************]  1 of 1 completed
Downloading: SQQQ interval = 1d  beg_date = 1980-01-01  end_date = None
[*********************100%***********************]  1 of 1 completed
In [257]:
MarketData.getDateRangesForStocks( ts_marketdat_mng.marketDataObj.getDataFrame() )
Out[257]:
Index Beg_Date End_Date
0 ^GSPC 1980-01-02 2021-10-28
1 ^IXIC 1980-01-02 2021-10-28
2 ^DJI 1992-01-02 2021-10-28
3 SPXL 2008-11-05 2021-10-28
4 SPXS 2008-11-19 2021-10-28
5 SDOW 2010-02-11 2021-10-28
6 SQQQ 2010-02-11 2021-10-28
7 TQQQ 2010-02-11 2021-10-28
8 UDOW 2010-02-11 2021-10-28

Simulation Broker

In [258]:
brokerTradingObj = SimBrokerTrading()

Trade Strategies, Trade Investment Manager, and Trade Asset Register Items

In [259]:
tsConfDat = TradeStrategyConfigData()

# Set Config

tsConfDat.tsSetConfig(\
    ts_set_conf_dict = 
           { 'set_actions_conf' : 
                      { "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
                        "exit"  : { 'votingPolicy' : 1, 
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1 } 
                      }
           } )
           
# TS #1

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_lstm_1",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 3,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'         : 20 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 1, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },
                             },
                    }  )

# TS #3

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_lstm_3",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'         : 20 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 1, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },
                             },
                    }  )

# TS #5

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_lstm_5",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps' : 40, 'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 3,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'         : 20 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 1, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },
                             },
                    }  )
In [260]:
taRegisterItems = [ ]
tsActionGen = TradeStrategyActionGenerator()

for trade_asset in portfolio_trade_assets :
    
    num_ts = len(tsConfDat.name_list) + 1  # adding the composite  trade strategy
    
    for i in range( num_ts ) :

        if i <= num_ts - 2:
            # *** Trade Strategy 

            actionDatItem  = tsConfDat.getTSConfigDataForItem(item_num = i )
            ts_unique_name = actionDatItem.name_list[0]
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = actionDatItem,
                                                     pipelineMng       = None )
        else :
            # Composite Trade Strategy 
            
            ts_unique_name = "all"            
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = tsConfDat,
                                                     pipelineMng       = None )

        ts_model = TradeStrategyBaseModelPersist(\
                        trade_asset               = trade_asset,
                        ts_marketdat_mng          = ts_marketdat_mng,
                        ts_enter                  = trade_enter_set,
                        ts_exit                   = trade_exit_set,                       
                        model_type                = ts_unique_name,
                        model_version             = "1.0",
                        market_data_period        = MarketDataPeriod.Day,
                    ) 

        # *** Trade Strategy Investment Manager 

        taInvMng = TradingAssetInvMngBase(\
                                        trade_asset                = trade_asset,
                                        minPeriodsBetweenTrades    = 1,
                                        initInvestment             = 1000000.0, 
                                        capPercentToInvestPerTrade = 100.0,
                                        minInvestPercent           = 5.0,
                                        min_account_balance        = 1000.0 )

        # *** Trade Register Item
        # *** This object has all configuration defined to execute a given trade strategy,
        # *** It can be executed individually in backtest or as part of a portfolio

        ta_registered_item = TradingAssetRegisterItem(\
                trade_name                    = "{0}_{1}".format(ts_unique_name, trade_asset), 
                ts_model                      = ts_model,
                tradingExecutionType          = TradingAssetExecutionType.Simulation,
                tradingBrokerObj              = brokerTradingObj,
                tradingAssetInvMngObj         = taInvMng )  

        taRegisterItems.append(ta_registered_item)
In [261]:
print("Number of configured Trade Asset Register Items: ", len(taRegisterItems) )
Number of configured Trade Asset Register Items:  12

Portfolio Investment Manager

In [262]:
# *** Porttfolio Investment Manager across all individual trade strategies investment managers
# *** Role: 
# ***    1) Managed investment funds across n number of trade strategies
# ***    2) Rebalance portfolio periodically or never
# ***    3) Portfolio Policy Weights 
# ***          equal weights (default)
# ***          MinimumVariance
# ***          User defined 
# ***    4) Track Portfolio level returns and metrics
# ***          Individual Trade Strategies return and metrics tracked through their 
# ***          investment managers
# ***          Portfolio funds are split across each trade strategy investment manager based on the
# ***          portfolio weights

portfInvMng = PortfolioInvMng(\
                  name                       = "Portfolio Inv. Manager for US-Indexes - Multiple-LSTM  TS",
                  initInvestment             = 2000000.0 * ( len(taRegisterItems) + 3),  # 200K/trade-strag
                  portfRebalanceFreq         = PortfolioRebalanceFrequency.Never,
                  portfRebalancePeriods      = 1,
                  minInvestPercent           = 5.0,
                  min_account_balance        = 1000.0,     
                  minPeriodsBetweenTrades    = 1,
                  capPercentToInvestPerTrade = 100.0 )

Trade Register Items Portfolio

In [263]:
# *** Set of Trade Register Items
#
# Configuration Summary:
#    - Each set has 1 to n trade register items as previously described 
#    - Optionally add long only trade strategies for all unique trade assets in the
#      portfolio 
#           - (Dow, Nasdaq, and S&P 500 for this portfolio) in this example
#           - Might be useful for bench marking trade strategies
#    - Each set has one Investment Portfolio Manager
#       - portfolio funds allocated per portfolio policy rules and re-balanced (if defined), 
#         across all trade strategies


portf_registered_obj = PortfolioRegisterItem(\
                        name                 = "Portfolio of US-Indexes with Multiple-LSTM and Long strategies",
                        taRegisterItems      = taRegisterItems,
                        portfolioInvMngObj   = portfInvMng,
                        tradingExecutionType = TradingAssetExecutionType.Simulation,
                        add_long_only_ts     = True )
2021-10-28 23:13:41,108 [INFO] root: *** Adding long only trade strategies for : {'^GSPC', '^IXIC', '^DJI'}

Training, Validation and Test Periods for Backtest

In Order to backtest a trade strategy or portfolio that has AI models, the following data is required:

  1. Training Date Range

    1. Date range that will be used to train the AI models in the backtest
  2. Validation Date Range

    1. Date range that twill be used to validate the AI models, should not overlapped with the training date range
  3. Test Period Date Range

    1. This is the out-sample date range, which corresponds to the date range of the backtest

Date Ranges are defined with a DatasetDef object, and have the following parameters:

  1. strBegDateAIModels : Date to begin training or validation of an AI model
  2. strBegDate : Date to begin the backtest
  3. strEndDate : Date to end training, validation and Backtest

Note:

  1. The param strBegDateAIModels can be defined as the same date as strBegDate, that is the default, if not defined.
  2. The critical aspect of using this parameter is in the backtest. Some AI Models, such as time series, others using moving averages over many periods, create params with no predicting data for those initial dates. Thus, in order to ensure the backtest starts on the actual date specified, the strBegDateAIModels should be defined as an earlier date, and it should not overlapped with the validation period end-date to avoid any chance of bias by picking at the validation data.
In [264]:
training_period = DatasetDef(datasetType = DatasetType.Training,
                             strBegDateAIModels = "1999-07-01",
                             strBegDate         = "2000-01-01",
                             strEndDate         = "2005-12-31" )

validation_period = DatasetDef(datasetType = DatasetType.Validation,
                               strBegDateAIModels = "2005-07-01",
                               strBegDate         = "2006-01-01",
                               strEndDate         = "2007-12-31" )

testing_period = DatasetDef(datasetType = DatasetType.Testing,
                               strBegDateAIModels = "2007-07-01",
                               strBegDate         = "2008-01-01",
                               strEndDate         = "2008-12-31" )

fit_datasets = FitDatasetsDef( trainingDataset    = training_period,
                               validationDataset  = validation_period )

Execute WFA Backtest

In [269]:
tsExecuteEngine = BacktestExecutionWFA( \
            name                        = "WFA Backtest for subset of Portfolio D - non-anchored training",
            test_period                 = testing_period,
            fit_datasets_start          = fit_datasets,
            trade_asset_registered_item = portf_registered_obj,
            wfa_slide_win_size          = 4,
            wfa_slide_win_period        = WFASlideWindowPeriod.Months, 
            anchor_fit_dataset          = False )                      
In [ ]:
tsExecuteEngine.evaluate()

Backtest Metrics

Execution & Investment Metrics
In [271]:
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
        'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']]
Out[271]:
TA_Reg_Name Is_Portfolio Num_Trades_Completed Init_Capital Final_Capital Cum_Return Backtest_Status
0 Portfolio of US-Indexes with Multiple-LSTM and... Yes 641 30000000.0 4.696890e+07 0.565630 Completed
1 ts_lstm_1_^DJI No 64 2000000.0 4.732744e+06 1.366372 Completed
2 ts_lstm_3_^DJI No 52 2000000.0 4.159925e+06 1.079962 Completed
3 ts_lstm_5_^DJI No 70 2000000.0 4.870862e+06 1.435431 Completed
4 all_^DJI No 62 2000000.0 4.309855e+06 1.154927 Completed
5 ts_lstm_1_^IXIC No 78 2000000.0 3.716019e+06 0.858009 Completed
6 ts_lstm_3_^IXIC No 76 2000000.0 5.669807e+06 1.834904 Completed
7 ts_lstm_5_^IXIC No 90 2000000.0 4.108412e+06 1.054206 Completed
8 all_^IXIC No 80 2000000.0 4.039707e+06 1.019853 Completed
9 ts_lstm_1_^GSPC No 22 2000000.0 2.463057e+06 0.231529 Completed
10 ts_lstm_3_^GSPC No 6 2000000.0 1.435241e+06 -0.282379 Completed
11 ts_lstm_5_^GSPC No 18 2000000.0 1.737240e+06 -0.131380 Completed
12 all_^GSPC No 20 2000000.0 1.921625e+06 -0.039187 Completed
13 Long-Only Trade Strategy for ^GSPC No 1 2000000.0 1.248316e+06 -0.375842 Completed
14 Long-Only Trade Strategy for ^IXIC No 1 2000000.0 1.209029e+06 -0.395486 Completed
15 Long-Only Trade Strategy for ^DJI No 1 2000000.0 1.347062e+06 -0.326469 Completed
Performance Metrics
In [272]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ]
Out[272]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
0 Portfolio of US-Indexes with Multiple-LSTM and... Yes 2008-01-03 2008-12-31 1.0 0.57 0.57 1.59 -0.18 0.11 -0.07
1 ts_lstm_1_^DJI No ts_lstm_1 ^DJI 2008-01-03 2008-12-31 1.0 1.37 1.38 2.46 -0.19 0.11 -0.07
2 ts_lstm_3_^DJI No ts_lstm_3 ^DJI 2008-01-03 2008-12-31 1.0 1.08 1.09 2.12 -0.19 0.11 -0.07
3 ts_lstm_5_^DJI No ts_lstm_5 ^DJI 2008-01-03 2008-12-31 1.0 1.44 1.45 2.53 -0.19 0.11 -0.07
4 all_^DJI No all ^DJI 2008-01-03 2008-12-31 1.0 1.15 1.16 2.2 -0.19 0.11 -0.07
5 ts_lstm_1_^IXIC No ts_lstm_1 ^IXIC 2008-01-03 2008-12-31 1.0 0.86 0.86 1.68 -0.24 0.12 -0.08
6 ts_lstm_3_^IXIC No ts_lstm_3 ^IXIC 2008-01-03 2008-12-31 1.0 1.83 1.85 2.75 -0.18 0.12 -0.07
7 ts_lstm_5_^IXIC No ts_lstm_5 ^IXIC 2008-01-03 2008-12-31 1.0 1.05 1.06 1.95 -0.21 0.12 -0.08
8 all_^IXIC No all ^IXIC 2008-01-03 2008-12-31 1.0 1.02 1.03 1.89 -0.24 0.12 -0.08
9 ts_lstm_1_^GSPC No ts_lstm_1 ^GSPC 2008-01-03 2008-12-31 1.0 0.23 0.23 0.71 -0.27 0.12 -0.09
10 ts_lstm_3_^GSPC No ts_lstm_3 ^GSPC 2008-01-03 2008-12-31 1.0 -0.28 -0.28 -0.6 -0.46 0.12 -0.09
11 ts_lstm_5_^GSPC No ts_lstm_5 ^GSPC 2008-01-03 2008-12-31 1.0 -0.13 -0.13 -0.14 -0.3 0.12 -0.09
12 all_^GSPC No all ^GSPC 2008-01-03 2008-12-31 1.0 -0.04 -0.04 0.11 -0.3 0.12 -0.09
13 Long-Only Trade Strategy for ^GSPC No long ^GSPC 2008-01-03 2008-12-31 1.0 -0.38 -0.38 -0.94 -0.48 0.12 -0.09
14 Long-Only Trade Strategy for ^IXIC No long ^IXIC 2008-01-03 2008-12-31 1.0 -0.4 -0.4 -1.02 -0.49 0.12 -0.09
15 Long-Only Trade Strategy for ^DJI No long ^DJI 2008-01-03 2008-12-31 1.0 -0.33 -0.33 -0.86 -0.42 0.11 -0.08
In [273]:
tsExecuteEngine.getSummaryMetrics().T.head(60)
Out[273]:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
ta_reg_item_name Portfolio of US-Indexes with Multiple-LSTM and... ts_lstm_1_^DJI ts_lstm_3_^DJI ts_lstm_5_^DJI all_^DJI ts_lstm_1_^IXIC ts_lstm_3_^IXIC ts_lstm_5_^IXIC all_^IXIC ts_lstm_1_^GSPC ts_lstm_3_^GSPC ts_lstm_5_^GSPC all_^GSPC Long-Only Trade Strategy for ^GSPC Long-Only Trade Strategy for ^IXIC Long-Only Trade Strategy for ^DJI
ta_reg_item_id None None None None None None None None None None None None None None None None
is_portfolio Yes No No No No No No No No No No No No No No No
model_type ts_lstm_1 ts_lstm_3 ts_lstm_5 all ts_lstm_1 ts_lstm_3 ts_lstm_5 all ts_lstm_1 ts_lstm_3 ts_lstm_5 all long long long
trade_asset ^DJI ^DJI ^DJI ^DJI ^IXIC ^IXIC ^IXIC ^IXIC ^GSPC ^GSPC ^GSPC ^GSPC ^GSPC ^IXIC ^DJI
test_period_len_days 365 365 365 365 365 365 365 365 365 365 365 365 365 365 365 365
tr_period_len_days 2191 2191 2191 2191 2191 2191 2191 2191 2191 2191 2191 2191 2191 2191 2191 2191
val_period_len_days 729 729 729 729 729 729 729 729 729 729 729 729 729 729 729 729
index Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy Strategy
Start Period 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03
End Period 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31 2008-12-31
Risk-Free Rate 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
Time in Market 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
Cumulative Return 0.57 1.37 1.08 1.44 1.15 0.86 1.83 1.05 1.02 0.23 -0.28 -0.13 -0.04 -0.38 -0.4 -0.33
CAGR% 0.57 1.38 1.09 1.45 1.16 0.86 1.85 1.06 1.03 0.23 -0.28 -0.13 -0.04 -0.38 -0.4 -0.33
Sharpe 1.59 2.46 2.12 2.53 2.2 1.68 2.75 1.95 1.89 0.71 -0.6 -0.14 0.11 -0.94 -1.02 -0.86
Sortino 2.7 4.44 3.75 4.48 3.86 2.76 4.99 3.2 3.11 1.12 -0.83 -0.2 0.16 -1.29 -1.4 -1.2
Sortino/√2 1.91 3.14 2.65 3.17 2.73 1.95 3.53 2.26 2.2 0.79 -0.59 -0.14 0.11 -0.91 -0.99 -0.85
Max Drawdown -0.18 -0.19 -0.19 -0.19 -0.19 -0.24 -0.18 -0.21 -0.24 -0.27 -0.46 -0.3 -0.3 -0.48 -0.49 -0.42
Longest DD Days 74 75 57 48 48 113 63 64 74 122 225 362 225 362 362 240
Volatility (ann.) 0.31 0.38 0.38 0.38 0.38 0.42 0.41 0.41 0.42 0.41 0.41 0.41 0.41 0.41 0.41 0.38
Calmar 3.13 7.13 5.63 7.47 6.01 3.56 10.55 5.18 4.23 0.87 -0.62 -0.44 -0.13 -0.79 -0.8 -0.78
Skew 1.17 0.93 0.9 0.84 0.87 0.64 0.8 0.5 0.6 0.72 0.14 0.45 0.41 0.18 0.21 0.43
Kurtosis 8.5 3.88 3.75 3.94 3.93 3.25 2.77 2.91 3.27 3.9 3.96 3.89 3.87 3.99 3.22 4.22
Expected Daily % 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0
Expected Monthly % 0.04 0.07 0.06 0.08 0.07 0.05 0.09 0.06 0.06 0.02 -0.03 -0.01 -0.0 -0.04 -0.04 -0.03
Expected Yearly % 0.57 1.37 1.08 1.44 1.15 0.86 1.83 1.05 1.02 0.23 -0.28 -0.13 -0.04 -0.38 -0.4 -0.33
Kelly Criterion 0.16 0.21 0.18 0.22 0.19 0.14 0.22 0.17 0.16 0.07 -0.06 -0.01 0.01 -0.1 -0.09 -0.08
Risk of Ruin 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
Daily Value-at-Risk -0.03 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04
Expected Shortfall (cVaR) -0.03 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04 -0.04
Gain/Pain Ratio 0.42 0.58 0.48 0.61 0.51 0.36 0.65 0.42 0.41 0.14 -0.11 -0.03 0.02 -0.16 -0.17 -0.15
Gain/Pain (1M) 4.28 8.85 10.56 11.3 9.87 2.15 16.07 5.68 3.06 1.02 -0.6 -0.17 0.15 -0.81 -0.69 -0.82
Payoff Ratio 1.23 1.25 1.25 1.19 1.19 1.12 1.3 1.12 1.11 1.03 0.83 0.92 0.92 0.83 0.96 0.92
Profit Factor 1.42 1.58 1.48 1.61 1.51 1.36 1.65 1.42 1.41 1.14 0.89 0.97 1.02 0.84 0.83 0.85
Common Sense Ratio 2.07 2.09 2.04 1.9 1.78 1.63 2.35 1.64 1.59 1.32 0.81 0.98 1.03 0.76 0.77 0.74
CPC Index 0.94 1.1 1.0 1.1 1.0 0.83 1.19 0.89 0.88 0.62 0.38 0.46 0.49 0.35 0.37 0.38
Tail Ratio 1.46 1.32 1.37 1.18 1.18 1.2 1.43 1.15 1.13 1.16 0.91 1.01 1.01 0.91 0.92 0.86
Outlier Win Ratio 5.11 4.74 4.49 4.85 4.83 4.85 4.58 4.71 4.83 5.34 4.24 4.75 4.75 4.26 3.61 4.23
Outlier Loss Ratio 5.56 3.52 3.69 3.59 3.58 3.49 3.38 3.53 3.49 3.71 4.29 3.93 3.92 4.3 4.04 4.23
MTD 0.27 0.32 0.24 0.27 0.32 0.43 0.37 0.34 0.37 0.4 0.01 0.13 0.16 0.01 0.03 -0.01
3M 0.23 0.59 0.37 0.37 0.42 0.2 0.59 0.22 0.15 0.2 -0.17 -0.03 -0.0 -0.18 -0.2 -0.15
6M 0.49 1.35 0.92 0.96 1.03 0.75 1.15 0.64 0.6 0.32 -0.28 -0.03 -0.0 -0.29 -0.31 -0.23
YTD 0.57 1.37 1.08 1.44 1.15 0.86 1.83 1.05 1.02 0.23 -0.28 -0.13 -0.04 -0.38 -0.4 -0.33
1Y 0.57 1.37 1.08 1.44 1.15 0.86 1.83 1.05 1.02 0.23 -0.28 -0.13 -0.04 -0.38 -0.4 -0.33
3Y (ann.) 0.57 1.38 1.09 1.45 1.16 0.86 1.85 1.06 1.03 0.23 -0.28 -0.13 -0.04 -0.38 -0.4 -0.33
5Y (ann.) 0.57 1.38 1.09 1.45 1.16 0.86 1.85 1.06 1.03 0.23 -0.28 -0.13 -0.04 -0.38 -0.4 -0.33
10Y (ann.) 0.57 1.38 1.09 1.45 1.16 0.86 1.85 1.06 1.03 0.23 -0.28 -0.13 -0.04 -0.38 -0.4 -0.33
All-time (ann.) 0.57 1.38 1.09 1.45 1.16 0.86 1.85 1.06 1.03 0.23 -0.28 -0.13 -0.04 -0.38 -0.4 -0.33
Best Day 0.11 0.11 0.11 0.11 0.11 0.12 0.12 0.12 0.12 0.12 0.12 0.12 0.12 0.12 0.12 0.11
Worst Day -0.07 -0.07 -0.07 -0.07 -0.07 -0.08 -0.07 -0.08 -0.08 -0.09 -0.09 -0.09 -0.09 -0.09 -0.09 -0.08
Best Month 0.27 0.32 0.28 0.27 0.32 0.43 0.37 0.34 0.37 0.4 0.07 0.13 0.16 0.05 0.06 0.05
Worst Month -0.09 -0.08 -0.03 -0.08 -0.08 -0.14 -0.05 -0.09 -0.14 -0.14 -0.15 -0.14 -0.14 -0.17 -0.18 -0.14
Best Year 0.57 1.37 1.08 1.44 1.15 0.86 1.83 1.05 1.02 0.23 -0.28 -0.13 -0.04 -0.38 -0.4 -0.33
Worst Year 0.57 1.37 1.08 1.44 1.15 0.86 1.83 1.05 1.02 0.23 -0.28 -0.13 -0.04 -0.38 -0.4 -0.33
Avg. Drawdown -0.03 -0.05 -0.04 -0.04 -0.04 -0.06 -0.03 -0.04 -0.04 -0.06 -0.07 -0.3 -0.06 -0.48 -0.49 -0.26
Avg. Drawdown Days 11 15 12 10 11 26 9 13 14 27 38 362 34 362 362 180
Recovery Factor 3.11 7.07 5.59 7.41 5.96 3.53 10.46 5.14 4.2 0.86 -0.61 -0.44 -0.13 -0.78 -0.8 -0.78
Ulcer Index 3.39 1.8 1.79 1.77 1.79 1.47 1.46 1.48 1.46 inf inf inf inf inf 1.56 1.86
Avg. Up Month 0.07 0.12 0.11 0.11 0.1 0.16 0.14 0.11 0.14 0.1 0.03 0.04 0.04 0.02 0.03 0.02

Persist Backtest to DB (optional )

In [ ]:
session.add( tsExecuteEngine )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst)
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")
In [ ]:
 

WFA-Backtest 2

Description:

  • Portfolio has a subset of the trade strategies in Portfolio G
    • Smaller subset of TA and AI models to reduce execution duration
  • Re-fit AI trading models every 6 months
  • Training-set is anchored

Backtest:

1. Type: WFA Backtest
2. AI Models Fit Date Ranges
    1. Training Period: 
        1. Begin Date = 2000-01-01 
        2. End Date   = 2005-12-31  
    2. Validation Period: 
        1. Begin Date = 2006-01-01 
        2. End Date   = 2007-12-31   
4. Test Period: 
    1. Begin Date = 2008-01-01 
    2. End Date   = 2010-12-31  

Portfolio Trade Assets

In [5]:
portfolio_trade_assets   = [ "^DJI", "^IXIC", "^GSPC" ]

Market Data Manager

In [6]:
dirPathMarketData = '/Users/gustavozambrana/Google Drive/Python/Projects/Trade_Engine/Data/US_Market_Indixes'

supportedTradeAssets   = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str           = "1980-01-01"
end_date_str           = None

ts_marketdat_mng = TradeStrategyMarketDataMng(\
        marketDataProviderName = "yahoofinance",
        supportedTradeAssets   = supportedTradeAssets,
        stock_price_col_name   = "Adj Close",
        fileNameMarketData     = "US_Indixes_And_ETFs_MrkData_From_1980",
        dirPathMarketData      = dirPathMarketData,
        beg_date_str           = beg_date_str,
        end_date_str           = end_date_str,
        interval               = "1d"  ) 
2021-10-29 09:33:42,132 [INFO] root: Found previous Market data previously loaded to specified file and dir.

Pipeline Data Manager

In [7]:
ts_model_pipline_mng_g = TradeStrategyModelPipelineDataMng(\
                            tsMarketDataMng    = ts_marketdat_mng,
                            package            = "trade_engine.model.ai.WaveNet_RNN_AI_PipelineBuilder",
                            model_class_name   = "WaveNet_RNN_AI_PipelineBuilder",
                            fileNameMarketData = "WaveNet_RNN_AI_Pipeline_Data_Portf_G",
                            forceCreatePipelineData = True,
                            dirPathMarketData  = dirPathMarketData )

Simulation Broker

In [8]:
brokerTradingObj = SimBrokerTrading()

Trade Strategies, Trade Investment Manager, and Trade Asset Register Items

In [9]:
tsConfDat = TradeStrategyConfigData()

# Set Config

tsConfDat.tsSetConfig(\
    ts_set_conf_dict = 
           { 'set_actions_conf' : 
                      { "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
                        "exit"  : { 'votingPolicy' : 1, 
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1 } 
                      }
           } )
           
# TS #1

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_gru_1", 
    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "gru",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'         : 20 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 1, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },

                               "stop_lost" :
                                    { 'model'    : "fix_perc",
                                      'type'     : "ta",
                                      'obj_args' : { 'long_stop_los_per' : 5, 'short_stop_los_per'    : 5 }  } 
                             },
                    }  )

# TS #2

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_lstm", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'         : 50,   'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn'   : True,
                                                 'epochs'          : 20 }  
                                }
                            } }  )
# TS #3
    
tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_conv1d_gru", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "conv1d_gru",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'   : 50,   'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'          : 20 }  
                                }
                            } }  )

# TS #8
tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_gru_2", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "gru",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'          : 40,   'no_neurons_lay1'    : 20,
                                         'no_neurons_lay2' : 20,   'pred_ahead_periods' : 3,
                                         'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                         'epochs'          : 20 }  
                                }
                            } }  )

# TS #10

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_2",    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 15, 'win_slow' : 60 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 },
                                },
                            }  } )

# TS #16

tsConfDat.addTSConf(\
   ts_conf_dict = { 
      'ts_unique_tag' : "ts_kama",    
      'actions_conf'  : { "entry_exit" :  
                            { 'model'    : "kama",
                              'type'     : "ta",
                              'obj_args' : { 'window_fast' : 10, 'pow1_fast' : 2, 'pow2_fast'  : 30,
                                             'window_slow' : 10, 'pow1_slow' : 5, 'pow2_slow'  : 30 },
                              'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                              'exit_policy_args'   : { 'lastn_match' : 1 },
                            },
                        }  } )
# TS #17

tsConfDat.addTSConf(\
   ts_conf_dict = { 
      'ts_unique_tag' : "ts_tsi",    
      'actions_conf'  : { "entry_exit" :  
                            { 'model'    : "tsi",
                              'type'     : "ta",
                              'obj_args' : { 'window_slow' : 25, 'window_fast' : 5 },
                              'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                              'exit_policy_args'   : { 'lastn_match' : 1 },
                            },
                        }  } )
In [10]:
taRegisterItems = [ ]
tsActionGen = TradeStrategyActionGenerator()

for trade_asset in portfolio_trade_assets :
    
    num_ts = len(tsConfDat.name_list) + 1  # adding the composite  trade strategy
    
    for i in range( num_ts ) :

        if i <= num_ts - 2:
            # *** Trade Strategy 

            actionDatItem  = tsConfDat.getTSConfigDataForItem(item_num = i )
            ts_unique_name = actionDatItem.name_list[0]
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = actionDatItem,
                                                     pipelineMng       = ts_model_pipline_mng_g )
        else :
            # Composite Trade Strategy 
            
            ts_unique_name = "all"            
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = tsConfDat,
                                                     pipelineMng       = ts_model_pipline_mng_g )

        ts_model = TradeStrategyBaseModelPersist(\
                        trade_asset               = trade_asset,
                        ts_marketdat_mng          = ts_marketdat_mng,
                        ts_enter                  = trade_enter_set,
                        ts_exit                   = trade_exit_set,                       
                        model_type                = ts_unique_name,
                        model_version             = "1.0",
                        market_data_period        = MarketDataPeriod.Day,
                    ) 

        # *** Trade Strategy Investment Manager 

        taInvMng = TradingAssetInvMngBase(\
                                        trade_asset                = trade_asset,
                                        minPeriodsBetweenTrades    = 1,
                                        initInvestment             = 1000000.0, 
                                        capPercentToInvestPerTrade = 100.0,
                                        minInvestPercent           = 5.0,
                                        min_account_balance        = 1000.0 )

        # *** Trade Register Item
        # *** This object has all configuration defined to execute a given trade strategy,
        # *** It can be executed individually in backtest or as part of a portfolio

        ta_registered_item = TradingAssetRegisterItem(\
                trade_name                    = "{0}_{1}".format(ts_unique_name, trade_asset), 
                ts_model                      = ts_model,
                tradingExecutionType          = TradingAssetExecutionType.Simulation,
                tradingBrokerObj              = brokerTradingObj,
                tradingAssetInvMngObj         = taInvMng )  

        taRegisterItems.append(ta_registered_item)
In [11]:
print("Number of configured Trade Asset Register Items: ", len(taRegisterItems) )
Number of configured Trade Asset Register Items:  24

Portfolio Investment Manager

In [12]:
# *** Porttfolio Investment Manager across all individual trade strategies investment managers
# *** Role: 
# ***    1) Managed investment funds across n number of trade strategies
# ***    2) Rebalance portfolio periodically or never
# ***    3) Portfolio Policy Weights 
# ***          equal weights (default)
# ***          MinimumVariance
# ***          User defined 
# ***    4) Track Portfolio level returns and metrics
# ***          Individual Trade Strategies return and metrics tracked through their 
# ***          investment managers
# ***          Portfolio funds are split across each trade strategy investment manager based on the
# ***          portfolio weights

portfInvMng = PortfolioInvMng(\
                  name                       = "Portfolio Inv. Manager for US-Indexes - TechAnal & AI Trading Models TS",
                  initInvestment             = 2000000.0 * ( len(taRegisterItems) + 3),  # 200K/trade-strag
                  portfRebalanceFreq         = PortfolioRebalanceFrequency.Never,
                  portfRebalancePeriods      = 1,
                  minInvestPercent           = 5.0,
                  min_account_balance        = 1000.0,     
                  minPeriodsBetweenTrades    = 1,
                  capPercentToInvestPerTrade = 100.0 )

Trade Register Items Portfolio

In [13]:
# *** Set of Trade Register Items
#
# Configuration Summary:
#    - Each set has 1 to n trade register items as previously described 
#    - Optionally add long only trade strategies for all unique trade assets in the
#      portfolio 
#           - (Dow, Nasdaq, and S&P 500 for this portfolio) in this example
#           - Might be useful for bench marking trade strategies
#    - Each set has one Investment Portfolio Manager
#       - portfolio funds allocated per portfolio policy rules and re-balanced (if defined), 
#         across all trade strategies


portf_registered_obj = PortfolioRegisterItem(\
                        name                 = "Portfolio of US-Indexes with TechAnal & AI Trading Models, and Long strategies",
                        taRegisterItems      = taRegisterItems,
                        portfolioInvMngObj   = portfInvMng,
                        tradingExecutionType = TradingAssetExecutionType.Simulation,
                        add_long_only_ts     = True )
2021-10-29 09:34:14,401 [INFO] root: *** Adding long only trade strategies for : {'^GSPC', '^IXIC', '^DJI'}

Training, Validation and Test Periods for Backtest

In Order to backtest a trade strategy or portfolio that has AI models, the following data is required:

  1. Training Date Range

    1. Date range that will be used to train the AI models in the backtest
  2. Validation Date Range

    1. Date range that twill be used to validate the AI models, should not overlapped with the training date range
  3. Test Period Date Range

    1. This is the out-sample date range, which corresponds to the date range of the backtest

Date Ranges are defined with a DatasetDef object, and have the following parameters:

  1. strBegDateAIModels : Date to begin training or validation of an AI model
  2. strBegDate : Date to begin the backtest
  3. strEndDate : Date to end training, validation and Backtest

Note:

  1. The param strBegDateAIModels can be defined as the same date as strBegDate, that is the default, if not defined.
  2. The critical aspect of using this parameter is in the backtest. Some AI Models, such as time series, others using moving averages over many periods, create params with no predicting data for those initial dates. Thus, in order to ensure the backtest starts on the actual date specified, the strBegDateAIModels should be defined as an earlier date, and it should not overlapped with the validation period end-date to avoid any chance of bias by picking at the validation data.
In [14]:
training_period = DatasetDef(datasetType = DatasetType.Training,
                             strBegDateAIModels = "1999-07-01",
                             strBegDate         = "2000-01-01",
                             strEndDate         = "2005-12-31" )

validation_period = DatasetDef(datasetType = DatasetType.Validation,
                               strBegDateAIModels = "2005-07-01",
                               strBegDate         = "2006-01-01",
                               strEndDate         = "2007-12-31" )

testing_period = DatasetDef(datasetType = DatasetType.Testing,
                               strBegDateAIModels = "2007-07-01",
                               strBegDate         = "2008-01-01",
                               strEndDate         = "2010-12-31" )

fit_datasets = FitDatasetsDef( trainingDataset    = training_period,
                               validationDataset  = validation_period )

Execute WFA Backtest

In [15]:
tsExecuteEngine = BacktestExecutionWFA( \
            name                        = "WFA Backtest for subset of Portfolio G - anchored training-set",
            test_period                 = testing_period,
            fit_datasets_start          = fit_datasets,
            trade_asset_registered_item = portf_registered_obj,
            wfa_slide_win_size          = 6,
            wfa_slide_win_period        = WFASlideWindowPeriod.Months, 
            anchor_fit_dataset          = True )                      
In [ ]:
tsExecuteEngine.evaluate()

Backtest Metrics

Trade Strategies Execution & Investment Metrics

DOW Jones

In [17]:
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
        'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
        query('TA_Reg_Name.str.contains("DJI")', engine='python')
Out[17]:
TA_Reg_Name Is_Portfolio Num_Trades_Completed Init_Capital Final_Capital Cum_Return Backtest_Status
1 ts_gru_1_^DJI No 237 2000000.0 4.702350e+06 1.351175 Completed
2 ts_lstm_^DJI No 195 2000000.0 4.397900e+06 1.198950 Completed
3 ts_conv1d_gru_^DJI No 192 2000000.0 5.047832e+06 1.523916 Completed
4 ts_gru_2_^DJI No 303 2000000.0 5.728731e+06 1.864365 Completed
5 ts_sma_2_^DJI No 12 2000000.0 2.659531e+06 0.329765 Completed
6 ts_kama_^DJI No 9 2000000.0 2.879268e+06 0.439634 Completed
7 ts_tsi_^DJI No 33 2000000.0 2.542929e+06 0.271465 Completed
8 all_^DJI No 239 2000000.0 5.629759e+06 1.814880 Completed
27 Long-Only Trade Strategy for ^DJI No 1 2000000.0 1.775633e+06 -0.112183 Completed

Nasdaq

In [18]:
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
        'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
        query('TA_Reg_Name.str.contains("IXIC")', engine='python')
Out[18]:
TA_Reg_Name Is_Portfolio Num_Trades_Completed Init_Capital Final_Capital Cum_Return Backtest_Status
9 ts_gru_1_^IXIC No 273 2000000.0 2.892646e+06 0.446323 Completed
10 ts_lstm_^IXIC No 259 2000000.0 5.371504e+06 1.685752 Completed
11 ts_conv1d_gru_^IXIC No 181 2000000.0 5.940391e+06 1.970195 Completed
12 ts_gru_2_^IXIC No 289 2000000.0 5.161725e+06 1.580863 Completed
13 ts_sma_2_^IXIC No 16 2000000.0 2.528602e+06 0.264301 Completed
14 ts_kama_^IXIC No 12 2000000.0 3.229503e+06 0.614752 Completed
15 ts_tsi_^IXIC No 30 2000000.0 2.700634e+06 0.350317 Completed
16 all_^IXIC No 238 2000000.0 6.027619e+06 2.013809 Completed
26 Long-Only Trade Strategy for ^IXIC No 1 2000000.0 2.033122e+06 0.016561 Completed

S&P 500

In [19]:
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
        'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
        query('TA_Reg_Name.str.contains("GSPC")', engine='python')
Out[19]:
TA_Reg_Name Is_Portfolio Num_Trades_Completed Init_Capital Final_Capital Cum_Return Backtest_Status
17 ts_gru_1_^GSPC No 241 2000000.0 3.800799e+06 0.900399 Completed
18 ts_lstm_^GSPC No 93 2000000.0 2.355349e+06 0.177675 Completed
19 ts_conv1d_gru_^GSPC No 136 2000000.0 3.257254e+06 0.628627 Completed
20 ts_gru_2_^GSPC No 221 2000000.0 4.945959e+06 1.472980 Completed
21 ts_sma_2_^GSPC No 15 2000000.0 2.967038e+06 0.483519 Completed
22 ts_kama_^GSPC No 5 2000000.0 3.511348e+06 0.755674 Completed
23 ts_tsi_^GSPC No 37 2000000.0 2.262027e+06 0.131013 Completed
24 all_^GSPC No 149 2000000.0 6.611552e+06 2.305776 Completed
25 Long-Only Trade Strategy for ^GSPC No 1 2000000.0 1.738083e+06 -0.130958 Completed
Performance Metrics

Dow Jones

In [20]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
        query('trade_asset == "^DJI" ')
Out[20]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
1 ts_gru_1_^DJI No ts_gru_1 ^DJI 2008-01-03 2010-12-31 1.0 1.35 0.33 1.16 -0.19 0.11 -0.07
2 ts_lstm_^DJI No ts_lstm ^DJI 2008-01-03 2010-12-31 1.0 1.2 0.3 1.09 -0.24 0.11 -0.07
3 ts_conv1d_gru_^DJI No ts_conv1d_gru ^DJI 2008-01-03 2010-12-31 1.0 1.52 0.36 1.25 -0.24 0.11 -0.07
4 ts_gru_2_^DJI No ts_gru_2 ^DJI 2008-01-03 2010-12-31 1.0 1.86 0.42 1.4 -0.19 0.11 -0.07
5 ts_sma_2_^DJI No ts_sma_2 ^DJI 2008-01-03 2010-12-31 0.99 0.33 0.1 0.58 -0.2 0.06 -0.06
6 ts_kama_^DJI No ts_kama ^DJI 2008-01-03 2010-12-31 1.0 0.44 0.13 0.74 -0.27 0.05 -0.05
7 ts_tsi_^DJI No ts_tsi ^DJI 2008-01-03 2010-12-31 0.96 0.27 0.08 0.47 -0.25 0.07 -0.07
8 all_^DJI No all ^DJI 2008-01-03 2010-12-31 1.0 1.81 0.41 1.38 -0.2 0.11 -0.07
27 Long-Only Trade Strategy for ^DJI No long ^DJI 2008-01-03 2010-12-31 1.0 -0.11 -0.04 -0.01 -0.5 0.11 -0.08
In [ ]:
tsExecuteEngine.getSummaryMetrics().query('trade_asset == "^DJI" ').T.head(60)

Nasdaq

In [21]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
        query('trade_asset == "^IXIC" ')
Out[21]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
9 ts_gru_1_^IXIC No ts_gru_1 ^IXIC 2008-01-03 2010-12-31 1.0 0.45 0.13 0.55 -0.4 0.12 -0.08
10 ts_lstm_^IXIC No ts_lstm ^IXIC 2008-01-03 2010-12-31 1.0 1.69 0.39 1.21 -0.24 0.12 -0.07
11 ts_conv1d_gru_^IXIC No ts_conv1d_gru ^IXIC 2008-01-03 2010-12-31 1.0 1.97 0.44 1.32 -0.21 0.12 -0.07
12 ts_gru_2_^IXIC No ts_gru_2 ^IXIC 2008-01-03 2010-12-31 1.0 1.58 0.37 1.16 -0.37 0.11 -0.12
13 ts_sma_2_^IXIC No ts_sma_2 ^IXIC 2008-01-03 2010-12-31 0.99 0.26 0.08 0.43 -0.31 0.09 -0.07
14 ts_kama_^IXIC No ts_kama ^IXIC 2008-01-03 2010-12-31 1.0 0.61 0.17 0.81 -0.22 0.08 -0.07
15 ts_tsi_^IXIC No ts_tsi ^IXIC 2008-01-03 2010-12-31 0.96 0.35 0.11 0.52 -0.33 0.08 -0.06
16 all_^IXIC No all ^IXIC 2008-01-03 2010-12-31 1.0 2.01 0.45 1.32 -0.26 0.11 -0.12
26 Long-Only Trade Strategy for ^IXIC No long ^IXIC 2008-01-03 2010-12-31 1.0 0.02 0.01 0.17 -0.51 0.12 -0.09
In [ ]:
tsExecuteEngine.getSummaryMetrics().query('trade_asset == "^IXIC" ').T.head(60)

S&P 500

In [22]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
        query('trade_asset == "^GSPC" ')
Out[22]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
17 ts_gru_1_^GSPC No ts_gru_1 ^GSPC 2008-01-03 2010-12-31 1.0 0.9 0.24 0.86 -0.25 0.12 -0.09
18 ts_lstm_^GSPC No ts_lstm ^GSPC 2008-01-03 2010-12-31 1.0 0.18 0.06 0.33 -0.43 0.12 -0.09
19 ts_conv1d_gru_^GSPC No ts_conv1d_gru ^GSPC 2008-01-03 2010-12-31 1.0 0.63 0.18 0.68 -0.27 0.12 -0.09
20 ts_gru_2_^GSPC No ts_gru_2 ^GSPC 2008-01-03 2010-12-31 1.0 1.47 0.35 1.15 -0.25 0.12 -0.09
21 ts_sma_2_^GSPC No ts_sma_2 ^GSPC 2008-01-03 2010-12-31 0.98 0.48 0.14 0.68 -0.25 0.07 -0.06
22 ts_kama_^GSPC No ts_kama ^GSPC 2008-01-03 2010-12-31 1.0 0.76 0.21 1.04 -0.15 0.06 -0.05
23 ts_tsi_^GSPC No ts_tsi ^GSPC 2008-01-03 2010-12-31 0.94 0.13 0.04 0.29 -0.27 0.08 -0.07
24 all_^GSPC No all ^GSPC 2008-01-03 2010-12-31 1.0 2.31 0.49 1.46 -0.19 0.12 -0.08
25 Long-Only Trade Strategy for ^GSPC No long ^GSPC 2008-01-03 2010-12-31 1.0 -0.13 -0.05 -0.0 -0.53 0.12 -0.09
In [ ]:
tsExecuteEngine.getSummaryMetrics().query('trade_asset == "^GSPC" ').T.head(60)

Persist Backtest to DB (optional )

In [ ]:
session.add( tsExecuteEngine )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst)
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")

WFA-Backtest 3

Description:

  • Portfolio has a subset of the trade strategies in Portfolio G
    • Smaller subset of TA and AI models to reduce execution duration
  • Re-fit AI trading models every 6 months
  • Training-set is not anchored

Backtest:

1. Type: WFA Backtest
2. AI Models Fit Date Ranges
    1. Training Period: 
        1. Begin Date = 2003-01-01 
        2. End Date   = 2008-12-31  
    2. Validation Period: 
        1. Begin Date = 2009-01-01 
        2. End Date   = 2010-12-31   
4. Test Period: 
    1. Begin Date = 2011-01-01 
    2. End Date   = 2012-12-31  

Portfolio Trade Assets

In [79]:
portfolio_trade_assets   = [ "^DJI", "^IXIC", "^GSPC" ]

Market Data Manager

In [80]:
dirPathMarketData = '/Users/gustavozambrana/Google Drive/Python/Projects/Trade_Engine/Data/US_Market_Indixes'

supportedTradeAssets   = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str           = "1980-01-01"
end_date_str           = None

ts_marketdat_mng = TradeStrategyMarketDataMng(\
        marketDataProviderName = "yahoofinance",
        supportedTradeAssets   = supportedTradeAssets,
        stock_price_col_name   = "Adj Close",
        fileNameMarketData     = "US_Indixes_And_ETFs_MrkData_From_1980",
        dirPathMarketData      = dirPathMarketData,
        beg_date_str           = beg_date_str,
        end_date_str           = end_date_str,
        interval               = "1d"  ) 
2021-10-30 20:31:13,213 [INFO] root: Found previous Market data previously loaded to specified file and dir.

Pipeline Data Manager

In [81]:
ts_model_pipline_mng_g = TradeStrategyModelPipelineDataMng(\
                            tsMarketDataMng    = ts_marketdat_mng,
                            package            = "trade_engine.model.ai.WaveNet_RNN_AI_PipelineBuilder",
                            model_class_name   = "WaveNet_RNN_AI_PipelineBuilder",
                            fileNameMarketData = "WaveNet_RNN_AI_Pipeline_Data_Portf_G",
                            forceCreatePipelineData = True,
                            dirPathMarketData  = dirPathMarketData )

Simulation Broker

In [82]:
brokerTradingObj = SimBrokerTrading()

Trade Strategies, Trade Investment Manager, and Trade Asset Register Items

In [83]:
tsConfDat = TradeStrategyConfigData()

# Set Config

tsConfDat.tsSetConfig(\
    ts_set_conf_dict = 
           { 'set_actions_conf' : 
                      { "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
                        "exit"  : { 'votingPolicy' : 1, 
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1 } 
                      }
           } )
           
# TS #1

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_gru_1", 
    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "gru",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'         : 20 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 1, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },

                               "stop_lost" :
                                    { 'model'    : "fix_perc",
                                      'type'     : "ta",
                                      'obj_args' : { 'long_stop_los_per' : 5, 'short_stop_los_per'    : 5 }  } 
                             },
                    }  )

# TS #2

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_lstm", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'         : 50,   'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn'   : True,
                                                 'epochs'          : 20 }  
                                }
                            } }  )
# TS #3
    
tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_conv1d_gru", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "conv1d_gru",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'   : 50,   'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'          : 20 }  
                                }
                            } }  )

# TS #8
tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_gru_2", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "gru",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'          : 40,   'no_neurons_lay1'    : 20,
                                         'no_neurons_lay2' : 20,   'pred_ahead_periods' : 3,
                                         'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                         'epochs'          : 20 }  
                                }
                            } }  )

# TS #10

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_2",    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 15, 'win_slow' : 60 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 },
                                },
                            }  } )

# TS #16

tsConfDat.addTSConf(\
   ts_conf_dict = { 
      'ts_unique_tag' : "ts_kama",    
      'actions_conf'  : { "entry_exit" :  
                            { 'model'    : "kama",
                              'type'     : "ta",
                              'obj_args' : { 'window_fast' : 10, 'pow1_fast' : 2, 'pow2_fast'  : 30,
                                             'window_slow' : 10, 'pow1_slow' : 5, 'pow2_slow'  : 30 },
                              'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                              'exit_policy_args'   : { 'lastn_match' : 1 },
                            },
                        }  } )
# TS #17

tsConfDat.addTSConf(\
   ts_conf_dict = { 
      'ts_unique_tag' : "ts_tsi",    
      'actions_conf'  : { "entry_exit" :  
                            { 'model'    : "tsi",
                              'type'     : "ta",
                              'obj_args' : { 'window_slow' : 25, 'window_fast' : 5 },
                              'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                              'exit_policy_args'   : { 'lastn_match' : 1 },
                            },
                        }  } )
In [84]:
taRegisterItems = [ ]
tsActionGen = TradeStrategyActionGenerator()

for trade_asset in portfolio_trade_assets :
    
    num_ts = len(tsConfDat.name_list) + 1  # adding the composite  trade strategy
    
    for i in range( num_ts ) :

        if i <= num_ts - 2:
            # *** Trade Strategy 

            actionDatItem  = tsConfDat.getTSConfigDataForItem(item_num = i )
            ts_unique_name = actionDatItem.name_list[0]
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = actionDatItem,
                                                     pipelineMng       = ts_model_pipline_mng_g )
        else :
            # Composite Trade Strategy 
            
            ts_unique_name = "all"            
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = tsConfDat,
                                                     pipelineMng       = ts_model_pipline_mng_g )

        ts_model = TradeStrategyBaseModelPersist(\
                        trade_asset               = trade_asset,
                        ts_marketdat_mng          = ts_marketdat_mng,
                        ts_enter                  = trade_enter_set,
                        ts_exit                   = trade_exit_set,                       
                        model_type                = ts_unique_name,
                        model_version             = "1.0",
                        market_data_period        = MarketDataPeriod.Day,
                    ) 

        # *** Trade Strategy Investment Manager 

        taInvMng = TradingAssetInvMngBase(\
                                        trade_asset                = trade_asset,
                                        minPeriodsBetweenTrades    = 1,
                                        initInvestment             = 1000000.0, 
                                        capPercentToInvestPerTrade = 100.0,
                                        minInvestPercent           = 5.0,
                                        min_account_balance        = 1000.0 )

        # *** Trade Register Item
        # *** This object has all configuration defined to execute a given trade strategy,
        # *** It can be executed individually in backtest or as part of a portfolio

        ta_registered_item = TradingAssetRegisterItem(\
                trade_name                    = "{0}_{1}".format(ts_unique_name, trade_asset), 
                ts_model                      = ts_model,
                tradingExecutionType          = TradingAssetExecutionType.Simulation,
                tradingBrokerObj              = brokerTradingObj,
                tradingAssetInvMngObj         = taInvMng )  

        taRegisterItems.append(ta_registered_item)
In [85]:
print("Number of configured Trade Asset Register Items: ", len(taRegisterItems) )
Number of configured Trade Asset Register Items:  24

Portfolio Investment Manager

In [86]:
# *** Porttfolio Investment Manager across all individual trade strategies investment managers
# *** Role: 
# ***    1) Managed investment funds across n number of trade strategies
# ***    2) Rebalance portfolio periodically or never
# ***    3) Portfolio Policy Weights 
# ***          equal weights (default)
# ***          MinimumVariance
# ***          User defined 
# ***    4) Track Portfolio level returns and metrics
# ***          Individual Trade Strategies return and metrics tracked through their 
# ***          investment managers
# ***          Portfolio funds are split across each trade strategy investment manager based on the
# ***          portfolio weights

portfInvMng = PortfolioInvMng(\
                  name                       = "Portfolio Inv. Manager for US-Indexes - TechAnal & AI Trading Models TS",
                  initInvestment             = 2000000.0 * ( len(taRegisterItems) + 3),  # 200K/trade-strag
                  portfRebalanceFreq         = PortfolioRebalanceFrequency.Never,
                  portfRebalancePeriods      = 1,
                  minInvestPercent           = 5.0,
                  min_account_balance        = 1000.0,     
                  minPeriodsBetweenTrades    = 1,
                  capPercentToInvestPerTrade = 100.0 )

Trade Register Items Portfolio

In [87]:
# *** Set of Trade Register Items
#
# Configuration Summary:
#    - Each set has 1 to n trade register items as previously described 
#    - Optionally add long only trade strategies for all unique trade assets in the
#      portfolio 
#           - (Dow, Nasdaq, and S&P 500 for this portfolio) in this example
#           - Might be useful for bench marking trade strategies
#    - Each set has one Investment Portfolio Manager
#       - portfolio funds allocated per portfolio policy rules and re-balanced (if defined), 
#         across all trade strategies


portf_registered_obj = PortfolioRegisterItem(\
                        name                 = "Portfolio of US-Indexes with TechAnal & AI Trading Models, and Long strategies",
                        taRegisterItems      = taRegisterItems,
                        portfolioInvMngObj   = portfInvMng,
                        tradingExecutionType = TradingAssetExecutionType.Simulation,
                        add_long_only_ts     = True )
2021-10-30 20:31:51,261 [INFO] root: *** Adding long only trade strategies for : {'^IXIC', '^DJI', '^GSPC'}

Training, Validation and Test Periods for Backtest

In Order to backtest a trade strategy or portfolio that has AI models, the following data is required:

  1. Training Date Range

    1. Date range that will be used to train the AI models in the backtest
  2. Validation Date Range

    1. Date range that twill be used to validate the AI models, should not overlapped with the training date range
  3. Test Period Date Range

    1. This is the out-sample date range, which corresponds to the date range of the backtest

Date Ranges are defined with a DatasetDef object, and have the following parameters:

  1. strBegDateAIModels : Date to begin training or validation of an AI model
  2. strBegDate : Date to begin the backtest
  3. strEndDate : Date to end training, validation and Backtest

Note:

  1. The param strBegDateAIModels can be defined as the same date as strBegDate, that is the default, if not defined.
  2. The critical aspect of using this parameter is in the backtest. Some AI Models, such as time series, others using moving averages over many periods, create params with no predicting data for those initial dates. Thus, in order to ensure the backtest starts on the actual date specified, the strBegDateAIModels should be defined as an earlier date, and it should not overlapped with the validation period end-date to avoid any chance of bias by picking at the validation data.
In [89]:
training_period = DatasetDef(datasetType = DatasetType.Training,
                             strBegDateAIModels = "2002-07-01",
                             strBegDate         = "2003-01-01",
                             strEndDate         = "2008-12-31" )

validation_period = DatasetDef(datasetType = DatasetType.Validation,
                               strBegDateAIModels = "2008-07-01",
                               strBegDate         = "2009-01-01",
                               strEndDate         = "2010-12-31" )

testing_period = DatasetDef(datasetType = DatasetType.Testing,
                               strBegDateAIModels = "2010-07-01",
                               strBegDate         = "2011-01-01",
                               strEndDate         = "2012-12-31" )

fit_datasets = FitDatasetsDef( trainingDataset    = training_period,
                               validationDataset  = validation_period )

Execute WFA Backtest

In [90]:
tsExecuteEngine = BacktestExecutionWFA( \
            name                        = "WFA Backtest-3 for subset of Portfolio G - anchored training-set",
            test_period                 = testing_period,
            fit_datasets_start          = fit_datasets,
            trade_asset_registered_item = portf_registered_obj,
            wfa_slide_win_size          = 6,
            wfa_slide_win_period        = WFASlideWindowPeriod.Months, 
            anchor_fit_dataset          = False )                      
In [ ]:
tsExecuteEngine.evaluate()

Backtest Metrics

Trade Strategies Execution & Investment Metrics

DOW Jones

In [92]:
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
        'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
        query('TA_Reg_Name.str.contains("DJI")', engine='python')
Out[92]:
TA_Reg_Name Is_Portfolio Num_Trades_Completed Init_Capital Final_Capital Cum_Return Backtest_Status
1 ts_gru_1_^DJI No 165 2000000.0 1.576387e+06 -0.211807 Completed
2 ts_lstm_^DJI No 93 2000000.0 2.160426e+06 0.080213 Completed
3 ts_conv1d_gru_^DJI No 105 2000000.0 2.468124e+06 0.234062 Completed
4 ts_gru_2_^DJI No 179 2000000.0 1.679280e+06 -0.160360 Completed
5 ts_sma_2_^DJI No 11 2000000.0 1.841726e+06 -0.079137 Completed
6 ts_kama_^DJI No 8 2000000.0 1.988360e+06 -0.005820 Completed
7 ts_tsi_^DJI No 26 2000000.0 1.758361e+06 -0.120820 Completed
8 all_^DJI No 115 2000000.0 2.046718e+06 0.023359 Completed
26 Long-Only Trade Strategy for ^DJI No 1 2000000.0 2.245110e+06 0.122555 Completed

Nasdaq

In [93]:
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
        'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
        query('TA_Reg_Name.str.contains("IXIC")', engine='python')
Out[93]:
TA_Reg_Name Is_Portfolio Num_Trades_Completed Init_Capital Final_Capital Cum_Return Backtest_Status
9 ts_gru_1_^IXIC No 143 2000000.0 2.138963e+06 0.069482 Completed
10 ts_lstm_^IXIC No 111 2000000.0 2.104373e+06 0.052187 Completed
11 ts_conv1d_gru_^IXIC No 101 2000000.0 2.356619e+06 0.178309 Completed
12 ts_gru_2_^IXIC No 173 2000000.0 1.912101e+06 -0.043949 Completed
13 ts_sma_2_^IXIC No 16 2000000.0 1.640432e+06 -0.179784 Completed
14 ts_kama_^IXIC No 11 2000000.0 1.496984e+06 -0.251508 Completed
15 ts_tsi_^IXIC No 25 2000000.0 1.806895e+06 -0.096552 Completed
16 all_^IXIC No 137 2000000.0 2.126406e+06 0.063203 Completed
25 Long-Only Trade Strategy for ^IXIC No 1 2000000.0 2.243697e+06 0.121848 Completed

S&P 500

In [94]:
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
        'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
        query('TA_Reg_Name.str.contains("GSPC")', engine='python')
Out[94]:
TA_Reg_Name Is_Portfolio Num_Trades_Completed Init_Capital Final_Capital Cum_Return Backtest_Status
17 ts_gru_1_^GSPC No 163 2000000.0 2.034552e+06 0.017276 Completed
18 ts_lstm_^GSPC No 115 2000000.0 2.301003e+06 0.150502 Completed
19 ts_conv1d_gru_^GSPC No 111 2000000.0 2.525937e+06 0.262968 Completed
20 ts_gru_2_^GSPC No 171 2000000.0 1.743395e+06 -0.128302 Completed
21 ts_sma_2_^GSPC No 12 2000000.0 1.942915e+06 -0.028543 Completed
22 ts_kama_^GSPC No 8 2000000.0 1.809392e+06 -0.095304 Completed
23 ts_tsi_^GSPC No 27 2000000.0 1.653393e+06 -0.173303 Completed
24 all_^GSPC No 141 2000000.0 2.073681e+06 0.036840 Completed
27 Long-Only Trade Strategy for ^GSPC No 1 2000000.0 2.242591e+06 0.121295 Completed
Performance Metrics

Dow Jones

In [95]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
        query('trade_asset == "^DJI" ')
Out[95]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
1 ts_gru_1_^DJI No ts_gru_1 ^DJI 2011-01-04 2012-12-31 1.0 -0.21 -0.11 -0.61 -0.31 0.05 -0.06
2 ts_lstm_^DJI No ts_lstm ^DJI 2011-01-04 2012-12-31 1.0 0.08 0.04 0.31 -0.19 0.04 -0.06
3 ts_conv1d_gru_^DJI No ts_conv1d_gru ^DJI 2011-01-04 2012-12-31 1.0 0.23 0.11 0.7 -0.17 0.04 -0.06
4 ts_gru_2_^DJI No ts_gru_2 ^DJI 2011-01-04 2012-12-31 1.0 -0.16 -0.08 -0.43 -0.24 0.05 -0.06
5 ts_sma_2_^DJI No ts_sma_2 ^DJI 2011-01-04 2012-12-31 0.99 -0.08 -0.04 -0.17 -0.24 0.06 -0.04
6 ts_kama_^DJI No ts_kama ^DJI 2011-01-04 2012-12-31 1.0 -0.01 -0.0 0.06 -0.16 0.05 -0.04
7 ts_tsi_^DJI No ts_tsi ^DJI 2011-01-04 2012-12-31 0.94 -0.12 -0.06 -0.34 -0.21 0.05 -0.04
8 all_^DJI No all ^DJI 2011-01-04 2012-12-31 1.0 0.02 0.01 0.15 -0.18 0.05 -0.06
26 Long-Only Trade Strategy for ^DJI No long ^DJI 2011-01-04 2012-12-31 1.0 0.12 0.06 0.43 -0.17 0.04 -0.06
In [ ]:
tsExecuteEngine.getSummaryMetrics().query('trade_asset == "^DJI" ').T.head(60)

Nasdaq

In [96]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
        query('trade_asset == "^IXIC" ')
Out[96]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
9 ts_gru_1_^IXIC No ts_gru_1 ^IXIC 2011-01-04 2012-12-31 1.0 0.07 0.03 0.27 -0.22 0.05 -0.07
10 ts_lstm_^IXIC No ts_lstm ^IXIC 2011-01-04 2012-12-31 1.0 0.05 0.03 0.23 -0.18 0.05 -0.07
11 ts_conv1d_gru_^IXIC No ts_conv1d_gru ^IXIC 2011-01-04 2012-12-31 1.0 0.18 0.09 0.5 -0.2 0.05 -0.07
12 ts_gru_2_^IXIC No ts_gru_2 ^IXIC 2011-01-04 2012-12-31 1.0 -0.04 -0.02 -0.0 -0.29 0.05 -0.07
13 ts_sma_2_^IXIC No ts_sma_2 ^IXIC 2011-01-04 2012-12-31 0.97 -0.18 -0.09 -0.39 -0.37 0.05 -0.07
14 ts_kama_^IXIC No ts_kama ^IXIC 2011-01-04 2012-12-31 1.0 -0.25 -0.14 -0.61 -0.31 0.07 -0.05
15 ts_tsi_^IXIC No ts_tsi ^IXIC 2011-01-04 2012-12-31 0.95 -0.1 -0.05 -0.17 -0.26 0.06 -0.04
16 all_^IXIC No all ^IXIC 2011-01-04 2012-12-31 1.0 0.06 0.03 0.25 -0.26 0.05 -0.07
25 Long-Only Trade Strategy for ^IXIC No long ^IXIC 2011-01-04 2012-12-31 1.0 0.12 0.06 0.38 -0.19 0.05 -0.07
In [ ]:
tsExecuteEngine.getSummaryMetrics().query('trade_asset == "^IXIC" ').T.head(60)

S&P 500

In [97]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
        query('trade_asset == "^GSPC" ')
Out[97]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
17 ts_gru_1_^GSPC No ts_gru_1 ^GSPC 2011-01-04 2012-12-31 1.0 0.02 0.01 0.14 -0.18 0.05 -0.07
18 ts_lstm_^GSPC No ts_lstm ^GSPC 2011-01-04 2012-12-31 1.0 0.15 0.07 0.46 -0.15 0.05 -0.07
19 ts_conv1d_gru_^GSPC No ts_conv1d_gru ^GSPC 2011-01-04 2012-12-31 1.0 0.26 0.12 0.71 -0.14 0.05 -0.07
20 ts_gru_2_^GSPC No ts_gru_2 ^GSPC 2011-01-04 2012-12-31 1.0 -0.13 -0.07 -0.27 -0.25 0.05 -0.07
21 ts_sma_2_^GSPC No ts_sma_2 ^GSPC 2011-01-04 2012-12-31 0.98 -0.03 -0.01 0.01 -0.23 0.07 -0.04
22 ts_kama_^GSPC No ts_kama ^GSPC 2011-01-04 2012-12-31 1.0 -0.1 -0.05 -0.2 -0.23 0.06 -0.04
23 ts_tsi_^GSPC No ts_tsi ^GSPC 2011-01-04 2012-12-31 0.95 -0.17 -0.09 -0.47 -0.24 0.06 -0.04
24 all_^GSPC No all ^GSPC 2011-01-04 2012-12-31 1.0 0.04 0.02 0.19 -0.18 0.05 -0.07
27 Long-Only Trade Strategy for ^GSPC No long ^GSPC 2011-01-04 2012-12-31 1.0 0.12 0.06 0.4 -0.19 0.05 -0.07
In [ ]:
tsExecuteEngine.getSummaryMetrics().query('trade_asset == "^GSPC" ').T.head(60)

Persist Backtest to DB (optional )

In [ ]:
session.add( tsExecuteEngine )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst)
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")

Slide Window WFA Backtest

- Description :

- Run a set of backtests by shifting the Training, Validation and Test Periods through time, or
  increasing the duration of the Training and Validation Periods through time and shifting only
  the Test Period
- Purpose of these set of backtest is to analysis the out-of-sample performance for trade strategies
  and/or portfolios through time
- The sliding-window of the training, validation, and test periods are configurable.
- This type of backtest is combined with the regular WFA backtest, which allows to re-fit
  models during each sliding window shift per the configuration of the regular WFA Backtest. 
- This type of backtest can be thought of as double sliding window, one sliding window for shifting or 
  increasing the size of the training and validation periods, the second one to control how often
  to re-fit models during a backtest.
- Due to the potential large number of backtests that can be executed, only the metadata, and summary 
  statistics and performance data are stored per backtest. 
      - All backtest statistical and metadata summary information is stored in a dataframe
      - The metadata information stored includes actual Fit Data Ranges, Test Period, and re-fit
        frequency during a backtest

- Example A:

- Scenario 1:
    - Fix Fit and Test Periods.

- Given the following initial setting for a backtest:

    Fit Dataset:   
        train:       1/1/2000 to 12/31/2004
        validation:  1/1/2005 to 12/31/2005

    Test Period:     1/1/2006 to 12/31/2006

- Run WFA backtests with the datasets above for different re-fit set frequencies, non-anchored:
    - 2 weeks
    - 1 month
    - 3 month

- This example will run the WFA defined part 1, three-times, re-fitting the AI models each time
  per the frequency defined.

- Example B:

- Scenario 2:
    - WFA Scenario implementation that slides through time the Fit datasets as well as the test period.

- Given the following initial setting for a backtest:

    Fit Dataset:   
        train:       1/1/2000 to 12/31/2004
        validation:  1/1/2005 to 12/31/2005

    Test Period:     1/1/2006 to 12/31/2006

- Run WFA backtests from the starting datasets above, incrementing sliding window of the datasets 
  for the Fit and Test periods by one-year, while the end date for the test period is less than 
  or equal to 12/31/2020

- Re-fit the AI Models in a backtest every 6 months, don't anchor the training set

- Each Iteration is one complete backtest, and in each backtest the AI Models are fitted at
  the start and at July 1 of the current backtest year.

    Iteration 1:
                    train:       1/1/2000 to 12/31/2004
                    validation:  1/1/2005 to 12/31/2005
                    Test Period: 1/1/2006 to 12/31/2006
    Iteration 2:
                    train:       1/1/2001 to 12/31/2005
                    validation:  1/1/2006 to 12/31/2006
                    Test Period: 1/1/2007 to 12/31/2007   
    ..
    ..
    Iteration Last:
        train:       1/1/2014 to 12/31/2018
        validation:  1/1/2019 to 12/31/2019
        Test Period: 1/1/2020 to 12/31/2020               

- Example C:

- Scenario 3:
    - WFA Scenario implementation that increases through time the date range of the Fit datasets, 
      but not the test period, as the fit dataset is anchored to its initial position. 
    - The train set is anchored, and the train and validation set are expanded in every iteration, 
      pushing the test period dataset forward in time, but with the same length. 
    - The increased per iteration of the train and validation set are configurable, as well as 
      the maximum end date for the test period.

- Given the following initial setting for a backtest:

    Fit Dataset:   
        train:       1/1/2000 to 12/31/2004
        validation:  1/1/2005 to 12/31/2005

    Test Period:     1/1/2006 to 12/31/2006

- Run WFA backtests from the starting datasets above, incrementing sliding window of the datasets 
  for the Fit and Test periods by one-year, while the end date for the test period is less than 
  or equal to 12/31/2020

- Re-fit the AI Models in a backtest every 6 months, don't anchor the training set

- This class will iterate through time by creating updated Fit datsets, and Test Periods, with 
  one year increments overall to the train and validation period. Train dataset increased by 9 months 
  per iteration, and Validation dataset by 3 months, the test period is just shifted by the one-year.
- that is:
    * Iteration 1:
                    train:       1/1/2000 to 12/31/2004
                    validation:  1/1/2005 to 12/31/2005
                    Test Period: 1/1/2006 to 12/31/2006
    * Iteration 2:
                    train:        1/1/2000  to  9/30/2005    (date range increased by nine-months)
                    validation:  10/1/2005  to 12/31/2006    (date range increaed by three-months and 
                                                              shifted by nine-months)
                    Test Period:  1/1/2007  to 12/31/2007    (date range shifted by one-year)
    * Iteration 3:
                    train:        1/1/2000  to  6/30/2006    (date range increased by nine-months)
                    validation:   7/1/2006  to 12/31/2007    (date range increaed by three-months and 
                                                              shifted by nine-months)
                    Test Period:  1/1/2008  to 12/31/2008    (date range shifted by one-year)
    ..
    ..

    * Iteration Last:
        train:       1/1/2000 to xxx
        validation:  yyy      to 12/31/2019       
        Test Period: 1/1/2020 to 12/31/2020                        

SW-WFA-Backtest 1

Description:

  • Portfolio has a subset of the trade strategies in Portfolio D
    • Smaller subset of AI models to reduce execution duration
  • Re-fit AI trading models every 3 months, then every 6 months within a backtest
  • Fixed Training and Validation periods
  • Training-set is not anchored during a backtest

Backtest:

1. Type: Slide Window WFA Backtest

2. AI Models Fit Date Ranges
    1. Training Period: 
        1. Begin Date = 2000-01-01 
        2. End Date   = 2005-12-31  
    2. Validation Period: 
        1. Begin Date = 2006-01-01 
        2. End Date   = 2007-12-31 

3. Test Period: 
    1. Begin Date = 2008-01-01 
    2. End Date   = 2008-12-31          

Portfolio Trade Assets

In [9]:
portfolio_trade_assets   = [ "^DJI", "^IXIC" ]

Market Data Manager

In [10]:
dirPathMarketData = '/Users/gustavozambrana/Google Drive/Python/Projects/Trade_Engine/Data/US_Market_Indixes'

supportedTradeAssets   = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str           = "1980-01-01"
end_date_str           = None

ts_marketdat_mng = TradeStrategyMarketDataMng(\
        marketDataProviderName = "yahoofinance",
        supportedTradeAssets   = supportedTradeAssets,
        stock_price_col_name   = "Adj Close",
        fileNameMarketData     = "US_Indixes_And_ETFs_MrkData_From_1980",
        dirPathMarketData      = dirPathMarketData,
        beg_date_str           = beg_date_str,
        end_date_str           = end_date_str,
        interval               = "1d"  ) 
2021-10-29 18:22:54,818 [INFO] root: Found previous Market data previously loaded to specified file and dir.
In [11]:
MarketData.getDateRangesForStocks( ts_marketdat_mng.marketDataObj.getDataFrame() )
Out[11]:
Index Beg_Date End_Date
0 ^GSPC 1980-01-02 2021-10-28
1 ^IXIC 1980-01-02 2021-10-28
2 ^DJI 1992-01-02 2021-10-28
3 SPXL 2008-11-05 2021-10-28
4 SPXS 2008-11-19 2021-10-28
5 SDOW 2010-02-11 2021-10-28
6 SQQQ 2010-02-11 2021-10-28
7 TQQQ 2010-02-11 2021-10-28
8 UDOW 2010-02-11 2021-10-28

Simulation Broker

In [12]:
brokerTradingObj = SimBrokerTrading()

Trade Strategies, Trade Investment Manager, and Trade Asset Register Items

In [13]:
tsConfDat = TradeStrategyConfigData()

# Set Config

tsConfDat.tsSetConfig(\
    ts_set_conf_dict = 
           { 'set_actions_conf' : 
                      { "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
                        "exit"  : { 'votingPolicy' : 1, 
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1 } 
                      }
           } )
           
# TS #1

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_lstm_1",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 3,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'         : 20 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 1, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },
                             },
                    }  )

# TS #3

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_lstm_3",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'         : 20 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 1, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },
                             },
                    }  )

# TS #5

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_lstm_5",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps' : 40, 'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 3,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'         : 20 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 1, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },
                             },
                    }  )
In [14]:
taRegisterItems = [ ]
tsActionGen = TradeStrategyActionGenerator()

for trade_asset in portfolio_trade_assets :
    
    num_ts = len(tsConfDat.name_list) + 1  # adding the composite  trade strategy
    
    for i in range( num_ts ) :

        if i <= num_ts - 2:
            # *** Trade Strategy 

            actionDatItem  = tsConfDat.getTSConfigDataForItem(item_num = i )
            ts_unique_name = actionDatItem.name_list[0]
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = actionDatItem,
                                                     pipelineMng       = None )
        else :
            # Composite Trade Strategy 
            
            ts_unique_name = "all"            
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = tsConfDat,
                                                     pipelineMng       = None )

        ts_model = TradeStrategyBaseModelPersist(\
                        trade_asset               = trade_asset,
                        ts_marketdat_mng          = ts_marketdat_mng,
                        ts_enter                  = trade_enter_set,
                        ts_exit                   = trade_exit_set,                       
                        model_type                = ts_unique_name,
                        model_version             = "1.0",
                        market_data_period        = MarketDataPeriod.Day,
                    ) 

        # *** Trade Strategy Investment Manager 

        taInvMng = TradingAssetInvMngBase(\
                                        trade_asset                = trade_asset,
                                        minPeriodsBetweenTrades    = 1,
                                        initInvestment             = 1000000.0, 
                                        capPercentToInvestPerTrade = 100.0,
                                        minInvestPercent           = 5.0,
                                        min_account_balance        = 1000.0 )

        # *** Trade Register Item
        # *** This object has all configuration defined to execute a given trade strategy,
        # *** It can be executed individually in backtest or as part of a portfolio

        ta_registered_item = TradingAssetRegisterItem(\
                trade_name                    = "{0}_{1}".format(ts_unique_name, trade_asset), 
                ts_model                      = ts_model,
                tradingExecutionType          = TradingAssetExecutionType.Simulation,
                tradingBrokerObj              = brokerTradingObj,
                tradingAssetInvMngObj         = taInvMng )  

        taRegisterItems.append(ta_registered_item)
In [15]:
print("Number of configured Trade Asset Register Items: ", len(taRegisterItems) )
Number of configured Trade Asset Register Items:  8

Portfolio Investment Manager

In [16]:
# *** Porttfolio Investment Manager across all individual trade strategies investment managers
# *** Role: 
# ***    1) Managed investment funds across n number of trade strategies
# ***    2) Rebalance portfolio periodically or never
# ***    3) Portfolio Policy Weights 
# ***          equal weights (default)
# ***          MinimumVariance
# ***          User defined 
# ***    4) Track Portfolio level returns and metrics
# ***          Individual Trade Strategies return and metrics tracked through their 
# ***          investment managers
# ***          Portfolio funds are split across each trade strategy investment manager based on the
# ***          portfolio weights

portfInvMng = PortfolioInvMng(\
                  name                       = "Portfolio Inv. Manager for US-Indexes - Multiple-LSTM  TS",
                  initInvestment             = 2000000.0 * ( len(taRegisterItems) + 3),  # 200K/trade-strag
                  portfRebalanceFreq         = PortfolioRebalanceFrequency.Never,
                  portfRebalancePeriods      = 1,
                  minInvestPercent           = 5.0,
                  min_account_balance        = 1000.0,     
                  minPeriodsBetweenTrades    = 1,
                  capPercentToInvestPerTrade = 100.0 )

Trade Register Items Portfolio

In [17]:
# *** Set of Trade Register Items
#
# Configuration Summary:
#    - Each set has 1 to n trade register items as previously described 
#    - Optionally add long only trade strategies for all unique trade assets in the
#      portfolio 
#           - (Dow, Nasdaq, and S&P 500 for this portfolio) in this example
#           - Might be useful for bench marking trade strategies
#    - Each set has one Investment Portfolio Manager
#       - portfolio funds allocated per portfolio policy rules and re-balanced (if defined), 
#         across all trade strategies


portf_registered_obj = PortfolioRegisterItem(\
                        name                 = "Portfolio of US-Indexes with Multiple-LSTM and Long strategies",
                        taRegisterItems      = taRegisterItems,
                        portfolioInvMngObj   = portfInvMng,
                        tradingExecutionType = TradingAssetExecutionType.Simulation,
                        add_long_only_ts     = True )
2021-10-29 18:23:46,474 [INFO] root: *** Adding long only trade strategies for : {'^IXIC', '^DJI'}

Training, Validation and Test Periods for Backtest

In Order to backtest a trade strategy or portfolio that has AI models, the following data is required:

  1. Training Date Range

    1. Date range that will be used to train the AI models in the backtest
  2. Validation Date Range

    1. Date range that twill be used to validate the AI models, should not overlapped with the training date range
  3. Test Period Date Range

    1. This is the out-sample date range, which corresponds to the date range of the backtest

Date Ranges are defined with a DatasetDef object, and have the following parameters:

  1. strBegDateAIModels : Date to begin training or validation of an AI model
  2. strBegDate : Date to begin the backtest
  3. strEndDate : Date to end training, validation and Backtest

Note:

  1. The param strBegDateAIModels can be defined as the same date as strBegDate, that is the default, if not defined.
  2. The critical aspect of using this parameter is in the backtest. Some AI Models, such as time series, others using moving averages over many periods, create params with no predicting data for those initial dates. Thus, in order to ensure the backtest starts on the actual date specified, the strBegDateAIModels should be defined as an earlier date, and it should not overlapped with the validation period end-date to avoid any chance of bias by picking at the validation data.
In [18]:
training_period = DatasetDef(datasetType = DatasetType.Training,
                             strBegDateAIModels = "1999-07-01",
                             strBegDate         = "2000-01-01",
                             strEndDate         = "2005-12-31" )

validation_period = DatasetDef(datasetType = DatasetType.Validation,
                               strBegDateAIModels = "2005-07-01",
                               strBegDate         = "2006-01-01",
                               strEndDate         = "2007-12-31" )

testing_period = DatasetDef(datasetType = DatasetType.Testing,
                               strBegDateAIModels = "2007-07-01",
                               strBegDate         = "2008-01-01",
                               strEndDate         = "2008-12-31" )

fit_datasets = FitDatasetsDef( trainingDataset    = training_period,
                               validationDataset  = validation_period )

Execute Slide Window WFA Backtest

In [20]:
tsExecuteEngine = BacktestExecutionSlideWindowWFA( \
            name                        = "SW WFA Backtest for subset of Portfolio D - non-anchored training",
            trade_asset_registered_item = portf_registered_obj,
            wfa_slide_win_size_list     = [ 3, 6] , # list of int, associated with wfa_slide_win_period_list                            
            wfa_slide_win_period_list   = [ WFASlideWindowPeriod.Months, WFASlideWindowPeriod.Months ],
            wfa_sw_scenario_obj         = WFASlideWinScenarioFixDatasets(fit_dataset = fit_datasets,
                                                                         test_period = testing_period ),
            anchor_fit_dataset          = False )  
        
In [ ]:
tsExecuteEngine.evaluate()

Backtest Metrics

Execution & Investment Metrics
In [24]:
tsExecuteEngine.getSummaryMetrics().info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 22 entries, 0 to 21
Data columns (total 72 columns):
 #   Column                      Non-Null Count  Dtype 
---  ------                      --------------  ----- 
 0   10Y (ann.)                  22 non-null     object
 1   1Y                          22 non-null     object
 2   3M                          22 non-null     object
 3   3Y (ann.)                   22 non-null     object
 4   5Y (ann.)                   22 non-null     object
 5   6M                          22 non-null     object
 6   All-time (ann.)             22 non-null     object
 7   Avg. Down Month             22 non-null     object
 8   Avg. Drawdown               22 non-null     object
 9   Avg. Drawdown Days          22 non-null     object
 10  Avg. Up Month               22 non-null     object
 11  Best Day                    22 non-null     object
 12  Best Month                  22 non-null     object
 13  Best Year                   22 non-null     object
 14  CAGR%                       22 non-null     object
 15  CPC Index                   22 non-null     object
 16  Calmar                      22 non-null     object
 17  Common Sense Ratio          22 non-null     object
 18  Cumulative Return           22 non-null     object
 19  Daily Value-at-Risk         22 non-null     object
 20  End Period                  22 non-null     object
 21  Expected Daily %            22 non-null     object
 22  Expected Monthly %          22 non-null     object
 23  Expected Shortfall (cVaR)   22 non-null     object
 24  Expected Yearly %           22 non-null     object
 25  Gain/Pain (1M)              22 non-null     object
 26  Gain/Pain Ratio             22 non-null     object
 27  Kelly Criterion             22 non-null     object
 28  Kurtosis                    22 non-null     object
 29  Longest DD Days             22 non-null     object
 30  MTD                         22 non-null     object
 31  Max Drawdown                22 non-null     object
 32  Outlier Loss Ratio          22 non-null     object
 33  Outlier Win Ratio           22 non-null     object
 34  Payoff Ratio                22 non-null     object
 35  Profit Factor               22 non-null     object
 36  Recovery Factor             22 non-null     object
 37  Risk of Ruin                22 non-null     object
 38  Risk-Free Rate              22 non-null     object
 39  Sharpe                      22 non-null     object
 40  Skew                        22 non-null     object
 41  Sortino                     22 non-null     object
 42  Sortino/√2                  22 non-null     object
 43  Start Period                22 non-null     object
 44  Tail Ratio                  22 non-null     object
 45  Time in Market              22 non-null     object
 46  Ulcer Index                 22 non-null     object
 47  Volatility (ann.)           22 non-null     object
 48  Win Days %                  22 non-null     object
 49  Win Month %                 22 non-null     object
 50  Win Quarter %               22 non-null     object
 51  Win Year %                  22 non-null     object
 52  Worst Day                   22 non-null     object
 53  Worst Month                 22 non-null     object
 54  Worst Year                  22 non-null     object
 55  YTD                         22 non-null     object
 56  anchor_fit_dataset          22 non-null     bool  
 57  index                       22 non-null     object
 58  is_portfolio                22 non-null     object
 59  model_type                  22 non-null     object
 60  ta_reg_item_id              0 non-null      object
 61  ta_reg_item_name            22 non-null     object
 62  test_period_len_days        22 non-null     int64 
 63  tr_period_len_days          22 non-null     int64 
 64  trade_asset                 22 non-null     object
 65  val_period_len_days         22 non-null     int64 
 66  wfa_slide_win_period        22 non-null     object
 67  wfa_slide_win_size          22 non-null     int64 
 68  wfa_sw_iter_no              22 non-null     int64 
 69  wfa_sw_name                 22 non-null     object
 70  wfa_sw_obj_size             22 non-null     int64 
 71  wfa_sw_scenario             22 non-null     object
dtypes: bool(1), int64(6), object(65)
memory usage: 12.3+ KB
Performance Metrics
In [36]:
tsExecuteEngine.getSummaryMetrics()\
[ [ 'wfa_sw_iter_no', 'wfa_slide_win_size', 'wfa_slide_win_period', 'tr_period_len_days', 'val_period_len_days',
    'test_period_len_days', 'ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 
    'Start Period', 'End Period', 'Time in Market ',
    'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ]
Out[36]:
wfa_sw_iter_no wfa_slide_win_size wfa_slide_win_period tr_period_len_days val_period_len_days test_period_len_days ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
0 1 3 Months 2191 729 365 Portfolio of US-Indexes with Multiple-LSTM and... Yes 2008-01-03 2008-12-31 1.0 0.86 0.86 2.06 -0.19 0.11 -0.06
1 1 3 Months 2191 729 365 ts_lstm_1_^DJI No ts_lstm_1 ^DJI 2008-01-03 2008-12-31 1.0 0.81 0.81 1.74 -0.22 0.11 -0.07
2 1 3 Months 2191 729 365 ts_lstm_3_^DJI No ts_lstm_3 ^DJI 2008-01-03 2008-12-31 1.0 1.24 1.25 2.31 -0.19 0.11 -0.07
3 1 3 Months 2191 729 365 ts_lstm_5_^DJI No ts_lstm_5 ^DJI 2008-01-03 2008-12-31 1.0 1.56 1.57 2.67 -0.19 0.11 -0.07
4 1 3 Months 2191 729 365 all_^DJI No all ^DJI 2008-01-03 2008-12-31 1.0 1.14 1.15 2.19 -0.19 0.11 -0.07
5 1 3 Months 2191 729 365 ts_lstm_1_^IXIC No ts_lstm_1 ^IXIC 2008-01-03 2008-12-31 1.0 0.72 0.72 1.52 -0.2 0.12 -0.09
6 1 3 Months 2191 729 365 ts_lstm_3_^IXIC No ts_lstm_3 ^IXIC 2008-01-03 2008-12-31 1.0 0.83 0.84 1.65 -0.21 0.12 -0.08
7 1 3 Months 2191 729 365 ts_lstm_5_^IXIC No ts_lstm_5 ^IXIC 2008-01-03 2008-12-31 1.0 1.48 1.49 2.42 -0.2 0.12 -0.08
8 1 3 Months 2191 729 365 all_^IXIC No all ^IXIC 2008-01-03 2008-12-31 1.0 1.5 1.51 2.44 -0.2 0.12 -0.08
9 1 3 Months 2191 729 365 Long-Only Trade Strategy for ^IXIC No long ^IXIC 2008-01-03 2008-12-31 1.0 -0.4 -0.4 -1.02 -0.49 0.12 -0.09
10 1 3 Months 2191 729 365 Long-Only Trade Strategy for ^DJI No long ^DJI 2008-01-03 2008-12-31 1.0 -0.33 -0.33 -0.86 -0.42 0.11 -0.08
11 2 6 Months 2191 729 365 Portfolio of US-Indexes with Multiple-LSTM and... Yes 2008-01-03 2008-12-31 1.0 0.88 0.88 2.06 -0.21 0.11 -0.06
12 2 6 Months 2191 729 365 ts_lstm_1_^DJI No ts_lstm_1 ^DJI 2008-01-03 2008-12-31 1.0 1.31 1.32 2.42 -0.22 0.11 -0.08
13 2 6 Months 2191 729 365 ts_lstm_3_^DJI No ts_lstm_3 ^DJI 2008-01-03 2008-12-31 1.0 1.3 1.31 2.38 -0.19 0.11 -0.07
14 2 6 Months 2191 729 365 ts_lstm_5_^DJI No ts_lstm_5 ^DJI 2008-01-03 2008-12-31 1.0 1.51 1.53 2.64 -0.22 0.11 -0.08
15 2 6 Months 2191 729 365 all_^DJI No all ^DJI 2008-01-03 2008-12-31 1.0 1.2 1.21 2.27 -0.22 0.11 -0.08
16 2 6 Months 2191 729 365 ts_lstm_1_^IXIC No ts_lstm_1 ^IXIC 2008-01-03 2008-12-31 1.0 1.18 1.19 2.1 -0.2 0.12 -0.08
17 2 6 Months 2191 729 365 ts_lstm_3_^IXIC No ts_lstm_3 ^IXIC 2008-01-03 2008-12-31 1.0 0.77 0.78 1.57 -0.23 0.12 -0.08
18 2 6 Months 2191 729 365 ts_lstm_5_^IXIC No ts_lstm_5 ^IXIC 2008-01-03 2008-12-31 1.0 1.03 1.04 1.91 -0.2 0.12 -0.08
19 2 6 Months 2191 729 365 all_^IXIC No all ^IXIC 2008-01-03 2008-12-31 1.0 1.18 1.19 2.1 -0.2 0.12 -0.08
20 2 6 Months 2191 729 365 Long-Only Trade Strategy for ^IXIC No long ^IXIC 2008-01-03 2008-12-31 1.0 -0.4 -0.4 -1.02 -0.49 0.12 -0.09
21 2 6 Months 2191 729 365 Long-Only Trade Strategy for ^DJI No long ^DJI 2008-01-03 2008-12-31 1.0 -0.33 -0.33 -0.86 -0.42 0.11 -0.08

Persist Backtest to DB (optional )

In [ ]:
session.add( tsExecuteEngine )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst)
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")

SW-WFA-Backtest 2

Description:

  • Portfolio has a subset of the trade strategies in Portfolio D
    • Smaller subset of AI models to reduce execution duration
  • Re-fit AI trading models every 6 months within a backtest
  • Slide Datasets by one year increments for five consecutive years
  • Training-set is not anchored in outer slide window or during a backtest

Backtest:

1. Type: Slide Window WFA Backtest

2. Start AI Models Fit Date Ranges
    1. Training Period: 
        1. Begin Date = 2000-01-01 
        2. End Date   = 2005-12-31  
    2. Validation Period: 
        1. Begin Date = 2006-01-01 
        2. End Date   = 2007-12-31 

3. Final AI Models Fit Date Ranges
    1. Training Period: 
        1. Begin Date = 2004-01-01 
        2. End Date   = 2009-12-31  
    2. Validation Period: 
        1. Begin Date = 2010-01-01 
        2. End Date   = 2011-12-31   

4. Start Test Period: 
    1. Begin Date = 2008-01-01 
    2. End Date   = 2008-12-31

5. Final Test Period: 
    1. Begin Date = 2012-01-01 
    2. End Date   = 2012-12-31     

Portfolio Trade Assets

In [50]:
portfolio_trade_assets   = [ "^DJI", "^IXIC" ]

Market Data Manager

In [51]:
dirPathMarketData = '/Users/gustavozambrana/Google Drive/Python/Projects/Trade_Engine/Data/US_Market_Indixes'

supportedTradeAssets   = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str           = "1980-01-01"
end_date_str           = None

ts_marketdat_mng = TradeStrategyMarketDataMng(\
        marketDataProviderName = "yahoofinance",
        supportedTradeAssets   = supportedTradeAssets,
        stock_price_col_name   = "Adj Close",
        fileNameMarketData     = "US_Indixes_And_ETFs_MrkData_From_1980",
        dirPathMarketData      = dirPathMarketData,
        beg_date_str           = beg_date_str,
        end_date_str           = end_date_str,
        interval               = "1d"  ) 
2021-10-29 23:07:12,449 [INFO] root: Found previous Market data previously loaded to specified file and dir.

Simulation Broker

In [52]:
brokerTradingObj = SimBrokerTrading()

Trade Strategies, Trade Investment Manager, and Trade Asset Register Items

In [53]:
tsConfDat = TradeStrategyConfigData()

# Set Config

tsConfDat.tsSetConfig(\
    ts_set_conf_dict = 
           { 'set_actions_conf' : 
                      { "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
                        "exit"  : { 'votingPolicy' : 1, 
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1 } 
                      }
           } )
           
# TS #1

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_lstm_1",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 3,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'         : 20 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 1, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },
                             },
                    }  )

# TS #3

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_lstm_3",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'         : 20 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 1, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },
                             },
                    }  )

# TS #5

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_lstm_5",     
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps' : 40, 'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 3,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'         : 20 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 1, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },
                             },
                    }  )
In [54]:
taRegisterItems = [ ]
tsActionGen = TradeStrategyActionGenerator()

for trade_asset in portfolio_trade_assets :
    
    num_ts = len(tsConfDat.name_list) + 1  # adding the composite  trade strategy
    
    for i in range( num_ts ) :

        if i <= num_ts - 2:
            # *** Trade Strategy 

            actionDatItem  = tsConfDat.getTSConfigDataForItem(item_num = i )
            ts_unique_name = actionDatItem.name_list[0]
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = actionDatItem,
                                                     pipelineMng       = None )
        else :
            # Composite Trade Strategy 
            
            ts_unique_name = "all"            
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = tsConfDat,
                                                     pipelineMng       = None )

        ts_model = TradeStrategyBaseModelPersist(\
                        trade_asset               = trade_asset,
                        ts_marketdat_mng          = ts_marketdat_mng,
                        ts_enter                  = trade_enter_set,
                        ts_exit                   = trade_exit_set,                       
                        model_type                = ts_unique_name,
                        model_version             = "1.0",
                        market_data_period        = MarketDataPeriod.Day,
                    ) 

        # *** Trade Strategy Investment Manager 

        taInvMng = TradingAssetInvMngBase(\
                                        trade_asset                = trade_asset,
                                        minPeriodsBetweenTrades    = 1,
                                        initInvestment             = 1000000.0, 
                                        capPercentToInvestPerTrade = 100.0,
                                        minInvestPercent           = 5.0,
                                        min_account_balance        = 1000.0 )

        # *** Trade Register Item
        # *** This object has all configuration defined to execute a given trade strategy,
        # *** It can be executed individually in backtest or as part of a portfolio

        ta_registered_item = TradingAssetRegisterItem(\
                trade_name                    = "{0}_{1}".format(ts_unique_name, trade_asset), 
                ts_model                      = ts_model,
                tradingExecutionType          = TradingAssetExecutionType.Simulation,
                tradingBrokerObj              = brokerTradingObj,
                tradingAssetInvMngObj         = taInvMng )  

        taRegisterItems.append(ta_registered_item)
In [55]:
print("Number of configured Trade Asset Register Items: ", len(taRegisterItems) )
Number of configured Trade Asset Register Items:  8

Portfolio Investment Manager

In [56]:
# *** Porttfolio Investment Manager across all individual trade strategies investment managers
# *** Role: 
# ***    1) Managed investment funds across n number of trade strategies
# ***    2) Rebalance portfolio periodically or never
# ***    3) Portfolio Policy Weights 
# ***          equal weights (default)
# ***          MinimumVariance
# ***          User defined 
# ***    4) Track Portfolio level returns and metrics
# ***          Individual Trade Strategies return and metrics tracked through their 
# ***          investment managers
# ***          Portfolio funds are split across each trade strategy investment manager based on the
# ***          portfolio weights

portfInvMng = PortfolioInvMng(\
                  name                       = "Portfolio Inv. Manager for US-Indexes - Multiple-LSTM  TS",
                  initInvestment             = 2000000.0 * ( len(taRegisterItems) + 3),  # 200K/trade-strag
                  portfRebalanceFreq         = PortfolioRebalanceFrequency.Never,
                  portfRebalancePeriods      = 1,
                  minInvestPercent           = 5.0,
                  min_account_balance        = 1000.0,     
                  minPeriodsBetweenTrades    = 1,
                  capPercentToInvestPerTrade = 100.0 )

Trade Register Items Portfolio

In [57]:
# *** Set of Trade Register Items
#
# Configuration Summary:
#    - Each set has 1 to n trade register items as previously described 
#    - Optionally add long only trade strategies for all unique trade assets in the
#      portfolio 
#           - (Dow, Nasdaq, and S&P 500 for this portfolio) in this example
#           - Might be useful for bench marking trade strategies
#    - Each set has one Investment Portfolio Manager
#       - portfolio funds allocated per portfolio policy rules and re-balanced (if defined), 
#         across all trade strategies


portf_registered_obj = PortfolioRegisterItem(\
                        name                 = "Portfolio of US-Indexes with Multiple-LSTM and Long strategies",
                        taRegisterItems      = taRegisterItems,
                        portfolioInvMngObj   = portfInvMng,
                        tradingExecutionType = TradingAssetExecutionType.Simulation,
                        add_long_only_ts     = True )
2021-10-29 23:07:30,659 [INFO] root: *** Adding long only trade strategies for : {'^IXIC', '^DJI'}

Training, Validation and Test Periods for Backtest

In Order to backtest a trade strategy or portfolio that has AI models, the following data is required:

  1. Training Date Range

    1. Date range that will be used to train the AI models in the backtest
  2. Validation Date Range

    1. Date range that twill be used to validate the AI models, should not overlapped with the training date range
  3. Test Period Date Range

    1. This is the out-sample date range, which corresponds to the date range of the backtest

Date Ranges are defined with a DatasetDef object, and have the following parameters:

  1. strBegDateAIModels : Date to begin training or validation of an AI model
  2. strBegDate : Date to begin the backtest
  3. strEndDate : Date to end training, validation and Backtest

Note:

  1. The param strBegDateAIModels can be defined as the same date as strBegDate, that is the default, if not defined.
  2. The critical aspect of using this parameter is in the backtest. Some AI Models, such as time series, others using moving averages over many periods, create params with no predicting data for those initial dates. Thus, in order to ensure the backtest starts on the actual date specified, the strBegDateAIModels should be defined as an earlier date, and it should not overlapped with the validation period end-date to avoid any chance of bias by picking at the validation data.
In [58]:
training_period = DatasetDef(datasetType = DatasetType.Training,
                             strBegDateAIModels = "1999-07-01",
                             strBegDate         = "2000-01-01",
                             strEndDate         = "2005-12-31" )

validation_period = DatasetDef(datasetType = DatasetType.Validation,
                               strBegDateAIModels = "2005-07-01",
                               strBegDate         = "2006-01-01",
                               strEndDate         = "2007-12-31" )

testing_period = DatasetDef(datasetType = DatasetType.Testing,
                               strBegDateAIModels = "2007-07-01",
                               strBegDate         = "2008-01-01",
                               strEndDate         = "2008-12-31" )

fit_datasets = FitDatasetsDef( trainingDataset    = training_period,
                               validationDataset  = validation_period )

Execute Slide Window WFA Backtest

In [59]:
tsExecuteEngine = BacktestExecutionSlideWindowWFA( \
    name                        = "SW WFA Backtest-2 for subset of Portfolio D - non-anchored training",
    trade_asset_registered_item = portf_registered_obj,
    wfa_slide_win_size_list     = [ 6 ] , # list of int, associated with wfa_slide_win_period_list                   
    wfa_slide_win_period_list   = [ WFASlideWindowPeriod.Months ],
    wfa_sw_scenario_obj         = WFASlideWinScenarioSlidingDatasets(\
                                        fit_dataset               = fit_datasets,
                                        test_period               = testing_period,
                                        slide_win_size            = 1,
                                        slide_win_period          = WFASlideWindowPeriod.Years,
                                        end_date_last_test_period = datetime(year=2012, month=12, day=31) ),
    anchor_fit_dataset          = False )
In [ ]:
tsExecuteEngine.evaluate()

Backtest Metrics

Performance Metrics
In [61]:
tsExecuteEngine.getSummaryMetrics()\
[ [ 'wfa_sw_iter_no', 'wfa_slide_win_size', 'wfa_slide_win_period', 'tr_period_len_days', 'val_period_len_days',
    'test_period_len_days', 'ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 
    'Start Period', 'End Period', 'Time in Market ',
    'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ]
Out[61]:
wfa_sw_iter_no wfa_slide_win_size wfa_slide_win_period tr_period_len_days val_period_len_days test_period_len_days ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
0 1 6 Months 2191 729 365 Portfolio of US-Indexes with Multiple-LSTM and... Yes 2008-01-03 2008-12-31 1.0 0.78 0.78 1.95 -0.18 0.11 -0.06
1 1 6 Months 2191 729 365 ts_lstm_1_^DJI No ts_lstm_1 ^DJI 2008-01-03 2008-12-31 1.0 0.94 0.94 1.93 -0.19 0.11 -0.07
2 1 6 Months 2191 729 365 ts_lstm_3_^DJI No ts_lstm_3 ^DJI 2008-01-03 2008-12-31 1.0 0.77 0.78 1.69 -0.24 0.11 -0.07
3 1 6 Months 2191 729 365 ts_lstm_5_^DJI No ts_lstm_5 ^DJI 2008-01-03 2008-12-31 1.0 1.56 1.57 2.68 -0.19 0.11 -0.07
4 1 6 Months 2191 729 365 all_^DJI No all ^DJI 2008-01-03 2008-12-31 1.0 0.82 0.82 1.76 -0.19 0.11 -0.07
5 1 6 Months 2191 729 365 ts_lstm_1_^IXIC No ts_lstm_1 ^IXIC 2008-01-03 2008-12-31 1.0 0.82 0.83 1.64 -0.19 0.12 -0.07
6 1 6 Months 2191 729 365 ts_lstm_3_^IXIC No ts_lstm_3 ^IXIC 2008-01-03 2008-12-31 1.0 1.32 1.33 2.25 -0.21 0.12 -0.07
7 1 6 Months 2191 729 365 ts_lstm_5_^IXIC No ts_lstm_5 ^IXIC 2008-01-03 2008-12-31 1.0 1.16 1.17 2.06 -0.23 0.12 -0.07
8 1 6 Months 2191 729 365 all_^IXIC No all ^IXIC 2008-01-03 2008-12-31 1.0 1.12 1.13 2.01 -0.23 0.12 -0.07
9 1 6 Months 2191 729 365 Long-Only Trade Strategy for ^IXIC No long ^IXIC 2008-01-03 2008-12-31 1.0 -0.4 -0.4 -1.02 -0.49 0.12 -0.09
10 1 6 Months 2191 729 365 Long-Only Trade Strategy for ^DJI No long ^DJI 2008-01-03 2008-12-31 1.0 -0.33 -0.33 -0.86 -0.42 0.11 -0.08
11 2 6 Months 2190 730 364 Portfolio of US-Indexes with Multiple-LSTM and... Yes 2009-01-05 2009-12-31 1.0 0.2 0.2 1.05 -0.13 0.07 -0.04
12 2 6 Months 2190 730 364 ts_lstm_1_^DJI No ts_lstm_1 ^DJI 2009-01-05 2009-12-31 1.0 0.13 0.13 0.63 -0.18 0.07 -0.04
13 2 6 Months 2190 730 364 ts_lstm_3_^DJI No ts_lstm_3 ^DJI 2009-01-05 2009-12-31 1.0 0.09 0.09 0.48 -0.2 0.07 -0.04
14 2 6 Months 2190 730 364 ts_lstm_5_^DJI No ts_lstm_5 ^DJI 2009-01-05 2009-12-31 1.0 0.29 0.3 1.18 -0.14 0.07 -0.04
15 2 6 Months 2190 730 364 all_^DJI No all ^DJI 2009-01-05 2009-12-31 1.0 0.05 0.05 0.31 -0.21 0.07 -0.04
16 2 6 Months 2190 730 364 ts_lstm_1_^IXIC No ts_lstm_1 ^IXIC 2009-01-05 2009-12-31 1.0 0.16 0.16 0.66 -0.25 0.07 -0.04
17 2 6 Months 2190 730 364 ts_lstm_3_^IXIC No ts_lstm_3 ^IXIC 2009-01-05 2009-12-31 1.0 0.16 0.16 0.65 -0.27 0.07 -0.04
18 2 6 Months 2190 730 364 ts_lstm_5_^IXIC No ts_lstm_5 ^IXIC 2009-01-05 2009-12-31 1.0 0.26 0.26 0.95 -0.24 0.07 -0.04
19 2 6 Months 2190 730 364 all_^IXIC No all ^IXIC 2009-01-05 2009-12-31 1.0 0.3 0.3 1.06 -0.25 0.07 -0.04
20 2 6 Months 2190 730 364 Long-Only Trade Strategy for ^IXIC No long ^IXIC 2009-01-05 2009-12-31 1.0 0.39 0.4 1.32 -0.23 0.07 -0.06
21 2 6 Months 2190 730 364 Long-Only Trade Strategy for ^DJI No long ^DJI 2009-01-05 2009-12-31 1.0 0.15 0.16 0.72 -0.27 0.07 -0.05
22 3 6 Months 2190 730 364 Portfolio of US-Indexes with Multiple-LSTM and... Yes 2010-01-05 2010-12-31 1.0 0.13 0.13 1.03 -0.06 0.04 -0.03
23 3 6 Months 2190 730 364 ts_lstm_1_^DJI No ts_lstm_1 ^DJI 2010-01-05 2010-12-31 1.0 0.22 0.22 1.32 -0.07 0.04 -0.04
24 3 6 Months 2190 730 364 ts_lstm_3_^DJI No ts_lstm_3 ^DJI 2010-01-05 2010-12-31 1.0 0.05 0.05 0.4 -0.12 0.04 -0.04
25 3 6 Months 2190 730 364 ts_lstm_5_^DJI No ts_lstm_5 ^DJI 2010-01-05 2010-12-31 1.0 0.13 0.13 0.85 -0.12 0.04 -0.04
26 3 6 Months 2190 730 364 all_^DJI No all ^DJI 2010-01-05 2010-12-31 1.0 0.08 0.08 0.56 -0.1 0.04 -0.04
27 3 6 Months 2190 730 364 ts_lstm_1_^IXIC No ts_lstm_1 ^IXIC 2010-01-05 2010-12-31 1.0 0.23 0.23 1.12 -0.18 0.05 -0.04
28 3 6 Months 2190 730 364 ts_lstm_3_^IXIC No ts_lstm_3 ^IXIC 2010-01-05 2010-12-31 1.0 0.06 0.06 0.38 -0.13 0.05 -0.04
29 3 6 Months 2190 730 364 ts_lstm_5_^IXIC No ts_lstm_5 ^IXIC 2010-01-05 2010-12-31 1.0 0.23 0.24 1.17 -0.1 0.05 -0.04
30 3 6 Months 2190 730 364 all_^IXIC No all ^IXIC 2010-01-05 2010-12-31 1.0 0.08 0.08 0.48 -0.13 0.05 -0.04
31 3 6 Months 2190 730 364 Long-Only Trade Strategy for ^IXIC No long ^IXIC 2010-01-05 2010-12-31 1.0 0.15 0.15 0.81 -0.17 0.05 -0.04
32 3 6 Months 2190 730 364 Long-Only Trade Strategy for ^DJI No long ^DJI 2010-01-05 2010-12-31 1.0 0.09 0.09 0.64 -0.13 0.04 -0.04
33 4 6 Months 2191 729 364 Portfolio of US-Indexes with Multiple-LSTM and... Yes 2011-01-04 2011-12-30 1.0 -0.11 -0.11 -0.66 -0.19 0.05 -0.04
34 4 6 Months 2191 729 364 ts_lstm_1_^DJI No ts_lstm_1 ^DJI 2011-01-04 2011-12-30 1.0 -0.2 -0.21 -0.98 -0.25 0.05 -0.06
35 4 6 Months 2191 729 364 ts_lstm_3_^DJI No ts_lstm_3 ^DJI 2011-01-04 2011-12-30 1.0 -0.04 -0.04 -0.09 -0.17 0.06 -0.04
36 4 6 Months 2191 729 364 ts_lstm_5_^DJI No ts_lstm_5 ^DJI 2011-01-04 2011-12-30 1.0 -0.05 -0.05 -0.14 -0.16 0.06 -0.04
37 4 6 Months 2191 729 364 all_^DJI No all ^DJI 2011-01-04 2011-12-30 1.0 -0.11 -0.12 -0.47 -0.17 0.06 -0.04
38 4 6 Months 2191 729 364 ts_lstm_1_^IXIC No ts_lstm_1 ^IXIC 2011-01-04 2011-12-30 1.0 -0.17 -0.17 -0.62 -0.34 0.05 -0.07
39 4 6 Months 2191 729 364 ts_lstm_3_^IXIC No ts_lstm_3 ^IXIC 2011-01-04 2011-12-30 1.0 -0.17 -0.17 -0.59 -0.32 0.05 -0.07
40 4 6 Months 2191 729 364 ts_lstm_5_^IXIC No ts_lstm_5 ^IXIC 2011-01-04 2011-12-30 1.0 -0.2 -0.2 -0.75 -0.29 0.05 -0.07
41 4 6 Months 2191 729 364 all_^IXIC No all ^IXIC 2011-01-04 2011-12-30 1.0 -0.19 -0.2 -0.73 -0.35 0.05 -0.07
42 4 6 Months 2191 729 364 Long-Only Trade Strategy for ^IXIC No long ^IXIC 2011-01-04 2011-12-30 1.0 -0.03 -0.03 -0.0 -0.19 0.05 -0.07
43 4 6 Months 2191 729 364 Long-Only Trade Strategy for ^DJI No long ^DJI 2011-01-04 2011-12-30 1.0 0.05 0.05 0.32 -0.17 0.04 -0.06
44 5 6 Months 2191 729 365 Portfolio of US-Indexes with Multiple-LSTM and... Yes 2012-01-04 2012-12-31 1.0 -0.01 -0.01 -0.04 -0.08 0.03 -0.03
45 5 6 Months 2191 729 365 ts_lstm_1_^DJI No ts_lstm_1 ^DJI 2012-01-04 2012-12-31 1.0 -0.09 -0.09 -0.75 -0.11 0.02 -0.02
46 5 6 Months 2191 729 365 ts_lstm_3_^DJI No ts_lstm_3 ^DJI 2012-01-04 2012-12-31 1.0 0.03 0.03 0.34 -0.1 0.02 -0.02
47 5 6 Months 2191 729 365 ts_lstm_5_^DJI No ts_lstm_5 ^DJI 2012-01-04 2012-12-31 1.0 0.03 0.03 0.31 -0.12 0.02 -0.02
48 5 6 Months 2191 729 365 all_^DJI No all ^DJI 2012-01-04 2012-12-31 1.0 -0.03 -0.03 -0.17 -0.12 0.02 -0.02
49 5 6 Months 2191 729 365 ts_lstm_1_^IXIC No ts_lstm_1 ^IXIC 2012-01-04 2012-12-31 1.0 -0.05 -0.05 -0.28 -0.1 0.03 -0.03
50 5 6 Months 2191 729 365 ts_lstm_3_^IXIC No ts_lstm_3 ^IXIC 2012-01-04 2012-12-31 1.0 -0.05 -0.05 -0.25 -0.15 0.03 -0.03
51 5 6 Months 2191 729 365 ts_lstm_5_^IXIC No ts_lstm_5 ^IXIC 2012-01-04 2012-12-31 1.0 -0.05 -0.05 -0.29 -0.1 0.03 -0.03
52 5 6 Months 2191 729 365 all_^IXIC No all ^IXIC 2012-01-04 2012-12-31 1.0 -0.07 -0.07 -0.44 -0.12 0.03 -0.03
53 5 6 Months 2191 729 365 Long-Only Trade Strategy for ^IXIC No long ^IXIC 2012-01-04 2012-12-31 1.0 0.14 0.14 0.96 -0.12 0.03 -0.03
54 5 6 Months 2191 729 365 Long-Only Trade Strategy for ^DJI No long ^DJI 2012-01-04 2012-12-31 1.0 0.06 0.06 0.54 -0.09 0.02 -0.02

Persist Backtest to DB (optional )

In [ ]:
session.add( tsExecuteEngine )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst)
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")

SW-WFA-Backtest 3

Description:

  • Portfolio has a subset of the trade strategies in Portfolio G
    • Smaller subset of AI models to reduce execution duration
  • Re-fit AI trading models every 6 months within a backtest and anchored within the backtest
  • Fit datasets are anchored and duration increased by one year increments for five consecutive years
    • Every sliding window iteration, the training set duration is increased by 9 months and the validation set by 3 months, the test set is just shifted by one year.
  • Training-set is anchored in outer slide window and also anchored in the re-fitting process during a backtest

Backtest:

  • Type: Slide Window WFA Backtest

  • Iteration 1:

       train:       1/1/2000 to 12/31/2005
       validation:  1/1/2006 to 12/31/2007
       Test Period: 1/1/2008 to 12/31/2008
  • Iteration 2:

       train:        1/1/2000  to  9/30/2006    (date range increased by nine-months)
       validation:  10/1/2006  to 12/31/2008    (date range increased by three-months and shifted 
                                                 by nine-months)
       Test Period:  1/1/2009  to 12/31/2009    (date range shifted by one-year)
  • Iteration 3:

       train:        1/1/2000  to  6/30/2007    (date range increased by nine-months)
       validation:   7/1/2007  to 12/31/2009    (date range increaed by three-months and shifted
                                                 by nine-months)
       Test Period:  1/1/2010  to 12/31/2010    (date range shifted by one-year)
    
       ...
       ...
  • Iteration Last:

       train:       1/1/2000 to xxx
       validation:  yyy      to 12/31/2011       
       Test Period: 1/1/2012 to 12/31/2012   
  • Each iteration corresponds to a WFA Backtest, and in each WFA Backtest, AI Models are re-fitted every six months with the training and validation set for the WFA backtest anchored.

Portfolio Trade Assets

In [62]:
portfolio_trade_assets   = [ "^DJI", "^IXIC", "^GSPC" ]

Market Data Manager

In [63]:
dirPathMarketData = '/Users/gustavozambrana/Google Drive/Python/Projects/Trade_Engine/Data/US_Market_Indixes'

supportedTradeAssets   = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str           = "1980-01-01"
end_date_str           = None

ts_marketdat_mng = TradeStrategyMarketDataMng(\
        marketDataProviderName = "yahoofinance",
        supportedTradeAssets   = supportedTradeAssets,
        stock_price_col_name   = "Adj Close",
        fileNameMarketData     = "US_Indixes_And_ETFs_MrkData_From_1980",
        dirPathMarketData      = dirPathMarketData,
        beg_date_str           = beg_date_str,
        end_date_str           = end_date_str,
        interval               = "1d"  ) 
2021-10-30 09:58:20,665 [INFO] root: Found previous Market data previously loaded to specified file and dir.

Pipeline Data Manager

In [64]:
ts_model_pipline_mng_g = TradeStrategyModelPipelineDataMng(\
                            tsMarketDataMng    = ts_marketdat_mng,
                            package            = "trade_engine.model.ai.WaveNet_RNN_AI_PipelineBuilder",
                            model_class_name   = "WaveNet_RNN_AI_PipelineBuilder",
                            fileNameMarketData = "WaveNet_RNN_AI_Pipeline_Data_Portf_G",
                            forceCreatePipelineData = True,
                            dirPathMarketData  = dirPathMarketData )

Simulation Broker

In [65]:
brokerTradingObj = SimBrokerTrading()

Trade Strategies, Trade Investment Manager, and Trade Asset Register Items

In [66]:
tsConfDat = TradeStrategyConfigData()

# Set Config

tsConfDat.tsSetConfig(\
    ts_set_conf_dict = 
           { 'set_actions_conf' : 
                      { "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
                        "exit"  : { 'votingPolicy' : 1, 
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1 } 
                      }
           } )
           
# TS #1

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_gru_1", 
    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "gru",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'         : 20 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 1, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },

                               "stop_lost" :
                                    { 'model'    : "fix_perc",
                                      'type'     : "ta",
                                      'obj_args' : { 'long_stop_los_per' : 5, 'short_stop_los_per'    : 5 }  } 
                             },
                    }  )

# TS #2

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_lstm", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'         : 50,   'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn'   : True,
                                                 'epochs'          : 20 }  
                                }
                            } }  )
# TS #3
    
tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_conv1d_gru", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "conv1d_gru",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'   : 50,   'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'          : 20 }  
                                }
                            } }  )

# TS #8
tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_gru_2", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "gru",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'          : 40,   'no_neurons_lay1'    : 20,
                                         'no_neurons_lay2' : 20,   'pred_ahead_periods' : 3,
                                         'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                         'epochs'          : 20 }  
                                }
                            } }  )

# TS #10

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_2",    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 15, 'win_slow' : 60 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 },
                                },
                            }  } )

# TS #16

tsConfDat.addTSConf(\
   ts_conf_dict = { 
      'ts_unique_tag' : "ts_kama",    
      'actions_conf'  : { "entry_exit" :  
                            { 'model'    : "kama",
                              'type'     : "ta",
                              'obj_args' : { 'window_fast' : 10, 'pow1_fast' : 2, 'pow2_fast'  : 30,
                                             'window_slow' : 10, 'pow1_slow' : 5, 'pow2_slow'  : 30 },
                              'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                              'exit_policy_args'   : { 'lastn_match' : 1 },
                            },
                        }  } )
# TS #17

tsConfDat.addTSConf(\
   ts_conf_dict = { 
      'ts_unique_tag' : "ts_tsi",    
      'actions_conf'  : { "entry_exit" :  
                            { 'model'    : "tsi",
                              'type'     : "ta",
                              'obj_args' : { 'window_slow' : 25, 'window_fast' : 5 },
                              'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                              'exit_policy_args'   : { 'lastn_match' : 1 },
                            },
                        }  } )
In [67]:
taRegisterItems = [ ]
tsActionGen = TradeStrategyActionGenerator()

for trade_asset in portfolio_trade_assets :
    
    num_ts = len(tsConfDat.name_list) + 1  # adding the composite  trade strategy
    
    for i in range( num_ts ) :

        if i <= num_ts - 2:
            # *** Trade Strategy 

            actionDatItem  = tsConfDat.getTSConfigDataForItem(item_num = i )
            ts_unique_name = actionDatItem.name_list[0]
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = actionDatItem,
                                                     pipelineMng       = ts_model_pipline_mng_g )
        else :
            # Composite Trade Strategy 
            
            ts_unique_name = "all"            
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = tsConfDat,
                                                     pipelineMng       = ts_model_pipline_mng_g )

        ts_model = TradeStrategyBaseModelPersist(\
                        trade_asset               = trade_asset,
                        ts_marketdat_mng          = ts_marketdat_mng,
                        ts_enter                  = trade_enter_set,
                        ts_exit                   = trade_exit_set,                       
                        model_type                = ts_unique_name,
                        model_version             = "1.0",
                        market_data_period        = MarketDataPeriod.Day,
                    ) 

        # *** Trade Strategy Investment Manager 

        taInvMng = TradingAssetInvMngBase(\
                                        trade_asset                = trade_asset,
                                        minPeriodsBetweenTrades    = 1,
                                        initInvestment             = 1000000.0, 
                                        capPercentToInvestPerTrade = 100.0,
                                        minInvestPercent           = 5.0,
                                        min_account_balance        = 1000.0 )

        # *** Trade Register Item
        # *** This object has all configuration defined to execute a given trade strategy,
        # *** It can be executed individually in backtest or as part of a portfolio

        ta_registered_item = TradingAssetRegisterItem(\
                trade_name                    = "{0}_{1}".format(ts_unique_name, trade_asset), 
                ts_model                      = ts_model,
                tradingExecutionType          = TradingAssetExecutionType.Simulation,
                tradingBrokerObj              = brokerTradingObj,
                tradingAssetInvMngObj         = taInvMng )  

        taRegisterItems.append(ta_registered_item)
In [68]:
print("Number of configured Trade Asset Register Items: ", len(taRegisterItems) )
Number of configured Trade Asset Register Items:  24

Portfolio Investment Manager

In [69]:
# *** Porttfolio Investment Manager across all individual trade strategies investment managers
# *** Role: 
# ***    1) Managed investment funds across n number of trade strategies
# ***    2) Rebalance portfolio periodically or never
# ***    3) Portfolio Policy Weights 
# ***          equal weights (default)
# ***          MinimumVariance
# ***          User defined 
# ***    4) Track Portfolio level returns and metrics
# ***          Individual Trade Strategies return and metrics tracked through their 
# ***          investment managers
# ***          Portfolio funds are split across each trade strategy investment manager based on the
# ***          portfolio weights

portfInvMng = PortfolioInvMng(\
                  name                       = "Portfolio Inv. Manager for US-Indexes - TechAnal & AI Trading Models TS",
                  initInvestment             = 2000000.0 * ( len(taRegisterItems) + 3),  # 200K/trade-strag
                  portfRebalanceFreq         = PortfolioRebalanceFrequency.Never,
                  portfRebalancePeriods      = 1,
                  minInvestPercent           = 5.0,
                  min_account_balance        = 1000.0,     
                  minPeriodsBetweenTrades    = 1,
                  capPercentToInvestPerTrade = 100.0 )

Trade Register Items Portfolio

In [70]:
# *** Set of Trade Register Items
#
# Configuration Summary:
#    - Each set has 1 to n trade register items as previously described 
#    - Optionally add long only trade strategies for all unique trade assets in the
#      portfolio 
#           - (Dow, Nasdaq, and S&P 500 for this portfolio) in this example
#           - Might be useful for bench marking trade strategies
#    - Each set has one Investment Portfolio Manager
#       - portfolio funds allocated per portfolio policy rules and re-balanced (if defined), 
#         across all trade strategies


portf_registered_obj = PortfolioRegisterItem(\
                        name                 = "Portfolio of US-Indexes with TechAnal & AI Trading Models, and Long strategies",
                        taRegisterItems      = taRegisterItems,
                        portfolioInvMngObj   = portfInvMng,
                        tradingExecutionType = TradingAssetExecutionType.Simulation,
                        add_long_only_ts     = True )
2021-10-30 09:59:37,285 [INFO] root: *** Adding long only trade strategies for : {'^IXIC', '^DJI', '^GSPC'}

Training, Validation and Test Periods for Backtest

In Order to backtest a trade strategy or portfolio that has AI models, the following data is required:

  1. Training Date Range

    1. Date range that will be used to train the AI models in the backtest
  2. Validation Date Range

    1. Date range that twill be used to validate the AI models, should not overlapped with the training date range
  3. Test Period Date Range

    1. This is the out-sample date range, which corresponds to the date range of the backtest

Date Ranges are defined with a DatasetDef object, and have the following parameters:

  1. strBegDateAIModels : Date to begin training or validation of an AI model
  2. strBegDate : Date to begin the backtest
  3. strEndDate : Date to end training, validation and Backtest

Note:

  1. The param strBegDateAIModels can be defined as the same date as strBegDate, that is the default, if not defined.
  2. The critical aspect of using this parameter is in the backtest. Some AI Models, such as time series, others using moving averages over many periods, create params with no predicting data for those initial dates. Thus, in order to ensure the backtest starts on the actual date specified, the strBegDateAIModels should be defined as an earlier date, and it should not overlapped with the validation period end-date to avoid any chance of bias by picking at the validation data.
In [71]:
training_period = DatasetDef(datasetType = DatasetType.Training,
                             strBegDateAIModels = "1999-07-01",
                             strBegDate         = "2000-01-01",
                             strEndDate         = "2005-12-31" )

validation_period = DatasetDef(datasetType = DatasetType.Validation,
                               strBegDateAIModels = "2005-07-01",
                               strBegDate         = "2006-01-01",
                               strEndDate         = "2007-12-31" )

testing_period = DatasetDef(datasetType = DatasetType.Testing,
                               strBegDateAIModels = "2007-07-01",
                               strBegDate         = "2008-01-01",
                               strEndDate         = "2008-12-31" )

fit_datasets = FitDatasetsDef( trainingDataset    = training_period,
                               validationDataset  = validation_period )

Execute Slide Window WFA Backtest

In [72]:
tsExecuteEngine = BacktestExecutionSlideWindowWFA( \
    name                        = "SW WFA Backtest-3 for subset of Portfolio G - anchored training",
    trade_asset_registered_item = portf_registered_obj,
    wfa_slide_win_size_list     = [ 6 ] , # list of int, associated with wfa_slide_win_period_list                   
    wfa_slide_win_period_list   = [ WFASlideWindowPeriod.Months ],
    wfa_sw_scenario_obj         = WFASlideWinScenarioAnchoredSlidingDatasets(\
                                        fit_dataset               = fit_datasets,
                                        test_period               = testing_period,
                                        train_slide_win_size      = 9, # increase train set 9 months every sw incr
                                        val_slide_win_size        = 3, # increase val set 3 months every sw incr
                                                                       # and shift by 9 months
                                        slide_win_period          = WFASlideWindowPeriod.Months,
                                        end_date_last_test_period = datetime(year=2012, month=12, day=31) ),
    anchor_fit_dataset          = True )
In [ ]:
tsExecuteEngine.evaluate()

Backtest Metrics

DJI
In [75]:
tsExecuteEngine.getSummaryMetrics()\
[ [ 'wfa_sw_iter_no', 'wfa_slide_win_size', 'wfa_slide_win_period', 'tr_period_len_days', 'val_period_len_days',
    'test_period_len_days', 'ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 
    'Start Period', 'End Period', 'Time in Market ',
    'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^DJI" ')
Out[75]:
wfa_sw_iter_no wfa_slide_win_size wfa_slide_win_period tr_period_len_days val_period_len_days test_period_len_days ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
1 1 6 Months 2191 729 365 ts_gru_1_^DJI No ts_gru_1 ^DJI 2008-01-03 2008-12-31 1.0 0.88 0.88 1.84 -0.19 0.11 -0.07
2 1 6 Months 2191 729 365 ts_lstm_^DJI No ts_lstm ^DJI 2008-01-03 2008-12-31 1.0 0.83 0.83 1.78 -0.24 0.11 -0.07
3 1 6 Months 2191 729 365 ts_conv1d_gru_^DJI No ts_conv1d_gru ^DJI 2008-01-03 2008-12-31 1.0 0.93 0.93 1.91 -0.24 0.11 -0.07
4 1 6 Months 2191 729 365 ts_gru_2_^DJI No ts_gru_2 ^DJI 2008-01-03 2008-12-31 1.0 0.96 0.96 1.95 -0.19 0.11 -0.07
5 1 6 Months 2191 729 365 ts_sma_2_^DJI No ts_sma_2 ^DJI 2008-01-03 2008-12-31 1.0 0.28 0.29 1.11 -0.09 0.06 -0.06
6 1 6 Months 2191 729 365 ts_kama_^DJI No ts_kama ^DJI 2008-01-03 2008-12-31 1.0 0.33 0.33 1.32 -0.09 0.05 -0.05
7 1 6 Months 2191 729 365 ts_tsi_^DJI No ts_tsi ^DJI 2008-01-03 2008-12-31 0.95 0.01 0.01 0.18 -0.2 0.07 -0.07
8 1 6 Months 2191 729 365 all_^DJI No all ^DJI 2008-01-03 2008-12-31 1.0 1.23 1.24 2.3 -0.19 0.11 -0.07
26 1 6 Months 2191 729 365 Long-Only Trade Strategy for ^DJI No long ^DJI 2008-01-03 2008-12-31 1.0 -0.33 -0.33 -0.86 -0.42 0.11 -0.08
29 2 6 Months 2464 821 364 ts_gru_1_^DJI No ts_gru_1 ^DJI 2009-01-05 2009-12-31 1.0 0.19 0.19 0.84 -0.16 0.07 -0.04
30 2 6 Months 2464 821 364 ts_lstm_^DJI No ts_lstm ^DJI 2009-01-05 2009-12-31 1.0 0.16 0.16 0.74 -0.18 0.07 -0.04
31 2 6 Months 2464 821 364 ts_conv1d_gru_^DJI No ts_conv1d_gru ^DJI 2009-01-05 2009-12-31 1.0 0.31 0.31 1.23 -0.13 0.07 -0.04
32 2 6 Months 2464 821 364 ts_gru_2_^DJI No ts_gru_2 ^DJI 2009-01-05 2009-12-31 1.0 0.18 0.18 0.79 -0.16 0.07 -0.04
33 2 6 Months 2464 821 364 ts_sma_2_^DJI No ts_sma_2 ^DJI 2009-01-05 2009-12-31 0.99 0.23 0.23 1.11 -0.17 0.04 -0.05
34 2 6 Months 2464 821 364 ts_kama_^DJI No ts_kama ^DJI 2009-01-05 2009-12-31 1.0 0.33 0.33 1.52 -0.19 0.04 -0.05
35 2 6 Months 2464 821 364 ts_tsi_^DJI No ts_tsi ^DJI 2009-01-05 2009-12-31 0.98 0.28 0.28 1.21 -0.11 0.07 -0.04
36 2 6 Months 2464 821 364 all_^DJI No all ^DJI 2009-01-05 2009-12-31 1.0 0.25 0.25 1.04 -0.11 0.07 -0.04
54 2 6 Months 2464 821 364 Long-Only Trade Strategy for ^DJI No long ^DJI 2009-01-05 2009-12-31 1.0 0.15 0.16 0.72 -0.27 0.07 -0.05
57 3 6 Months 2737 913 364 ts_gru_1_^DJI No ts_gru_1 ^DJI 2010-01-05 2010-12-31 1.0 -0.01 -0.01 0.01 -0.13 0.04 -0.04
58 3 6 Months 2737 913 364 ts_lstm_^DJI No ts_lstm ^DJI 2010-01-05 2010-12-31 1.0 0.15 0.16 0.96 -0.08 0.04 -0.04
59 3 6 Months 2737 913 364 ts_conv1d_gru_^DJI No ts_conv1d_gru ^DJI 2010-01-05 2010-12-31 1.0 -0.14 -0.15 -0.86 -0.27 0.04 -0.04
60 3 6 Months 2737 913 364 ts_gru_2_^DJI No ts_gru_2 ^DJI 2010-01-05 2010-12-31 1.0 0.28 0.28 1.61 -0.1 0.04 -0.04
61 3 6 Months 2737 913 364 ts_sma_2_^DJI No ts_sma_2 ^DJI 2010-01-05 2010-12-31 0.98 -0.12 -0.12 -0.71 -0.2 0.04 -0.03
62 3 6 Months 2737 913 364 ts_kama_^DJI No ts_kama ^DJI 2010-01-05 2010-12-31 1.0 -0.16 -0.16 -1.0 -0.27 0.04 -0.04
63 3 6 Months 2737 913 364 ts_tsi_^DJI No ts_tsi ^DJI 2010-01-05 2010-12-31 0.96 -0.03 -0.03 -0.12 -0.12 0.04 -0.04
64 3 6 Months 2737 913 364 all_^DJI No all ^DJI 2010-01-05 2010-12-31 1.0 0.07 0.07 0.49 -0.15 0.04 -0.04
82 3 6 Months 2737 913 364 Long-Only Trade Strategy for ^DJI No long ^DJI 2010-01-05 2010-12-31 1.0 0.09 0.09 0.64 -0.13 0.04 -0.04
85 4 6 Months 3011 1003 364 ts_gru_1_^DJI No ts_gru_1 ^DJI 2011-01-04 2011-12-30 1.0 -0.1 -0.1 -0.38 -0.21 0.06 -0.04
86 4 6 Months 3011 1003 364 ts_lstm_^DJI No ts_lstm ^DJI 2011-01-04 2011-12-30 1.0 0.07 0.07 0.42 -0.15 0.06 -0.04
87 4 6 Months 3011 1003 364 ts_conv1d_gru_^DJI No ts_conv1d_gru ^DJI 2011-01-04 2011-12-30 1.0 -0.11 -0.11 -0.43 -0.22 0.05 -0.06
88 4 6 Months 3011 1003 364 ts_gru_2_^DJI No ts_gru_2 ^DJI 2011-01-04 2011-12-30 1.0 -0.03 -0.03 -0.04 -0.2 0.06 -0.04
89 4 6 Months 3011 1003 364 ts_sma_2_^DJI No ts_sma_2 ^DJI 2011-01-04 2011-12-30 0.99 -0.09 -0.09 -0.36 -0.24 0.06 -0.04
90 4 6 Months 3011 1003 364 ts_kama_^DJI No ts_kama ^DJI 2011-01-04 2011-12-30 1.0 0.06 0.06 0.39 -0.12 0.05 -0.04
91 4 6 Months 3011 1003 364 ts_tsi_^DJI No ts_tsi ^DJI 2011-01-04 2011-12-30 0.96 -0.06 -0.06 -0.21 -0.16 0.05 -0.04
92 4 6 Months 3011 1003 364 all_^DJI No all ^DJI 2011-01-04 2011-12-30 1.0 0.02 0.02 0.2 -0.17 0.06 -0.04
110 4 6 Months 3011 1003 364 Long-Only Trade Strategy for ^DJI No long ^DJI 2011-01-04 2011-12-30 1.0 0.05 0.05 0.32 -0.17 0.04 -0.06
113 5 6 Months 3286 1093 365 ts_gru_1_^DJI No ts_gru_1 ^DJI 2012-01-04 2012-12-31 1.0 -0.06 -0.06 -0.49 -0.16 0.02 -0.02
114 5 6 Months 3286 1093 365 ts_lstm_^DJI No ts_lstm ^DJI 2012-01-04 2012-12-31 1.0 -0.12 -0.13 -1.09 -0.14 0.02 -0.02
115 5 6 Months 3286 1093 365 ts_conv1d_gru_^DJI No ts_conv1d_gru ^DJI 2012-01-04 2012-12-31 1.0 -0.04 -0.04 -0.3 -0.15 0.02 -0.02
116 5 6 Months 3286 1093 365 ts_gru_2_^DJI No ts_gru_2 ^DJI 2012-01-04 2012-12-31 1.0 0.03 0.03 0.29 -0.08 0.02 -0.02
117 5 6 Months 3286 1093 365 ts_sma_2_^DJI No ts_sma_2 ^DJI 2012-01-04 2012-12-31 0.98 -0.0 -0.0 0.03 -0.11 0.02 -0.02
118 5 6 Months 3286 1093 365 ts_kama_^DJI No ts_kama ^DJI 2012-01-04 2012-12-31 1.0 -0.07 -0.07 -0.6 -0.15 0.02 -0.02
119 5 6 Months 3286 1093 365 ts_tsi_^DJI No ts_tsi ^DJI 2012-01-04 2012-12-31 0.93 -0.08 -0.08 -0.74 -0.15 0.02 -0.02
120 5 6 Months 3286 1093 365 all_^DJI No all ^DJI 2012-01-04 2012-12-31 1.0 -0.07 -0.07 -0.61 -0.1 0.02 -0.02
138 5 6 Months 3286 1093 365 Long-Only Trade Strategy for ^DJI No long ^DJI 2012-01-04 2012-12-31 1.0 0.06 0.06 0.54 -0.09 0.02 -0.02
Nasdaq
In [77]:
tsExecuteEngine.getSummaryMetrics()\
[ [ 'wfa_sw_iter_no', 'wfa_slide_win_size', 'wfa_slide_win_period', 'tr_period_len_days', 'val_period_len_days',
    'test_period_len_days', 'ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 
    'Start Period', 'End Period', 'Time in Market ',
    'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^IXIC" ')
Out[77]:
wfa_sw_iter_no wfa_slide_win_size wfa_slide_win_period tr_period_len_days val_period_len_days test_period_len_days ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
9 1 6 Months 2191 729 365 ts_gru_1_^IXIC No ts_gru_1 ^IXIC 2008-01-03 2008-12-31 1.0 0.65 0.65 1.4 -0.28 0.12 -0.08
10 1 6 Months 2191 729 365 ts_lstm_^IXIC No ts_lstm ^IXIC 2008-01-03 2008-12-31 1.0 1.24 1.25 2.16 -0.21 0.12 -0.07
11 1 6 Months 2191 729 365 ts_conv1d_gru_^IXIC No ts_conv1d_gru ^IXIC 2008-01-03 2008-12-31 1.0 1.13 1.14 2.04 -0.21 0.12 -0.07
12 1 6 Months 2191 729 365 ts_gru_2_^IXIC No ts_gru_2 ^IXIC 2008-01-03 2008-12-31 1.0 0.93 0.94 1.78 -0.37 0.11 -0.12
13 1 6 Months 2191 729 365 ts_sma_2_^IXIC No ts_sma_2 ^IXIC 2008-01-03 2008-12-31 0.99 0.27 0.28 0.98 -0.19 0.09 -0.07
14 1 6 Months 2191 729 365 ts_kama_^IXIC No ts_kama ^IXIC 2008-01-03 2008-12-31 1.0 0.28 0.29 1.02 -0.22 0.08 -0.07
15 1 6 Months 2191 729 365 ts_tsi_^IXIC No ts_tsi ^IXIC 2008-01-03 2008-12-31 0.96 0.33 0.33 1.14 -0.15 0.08 -0.06
16 1 6 Months 2191 729 365 all_^IXIC No all ^IXIC 2008-01-03 2008-12-31 1.0 1.52 1.53 2.41 -0.26 0.11 -0.12
25 1 6 Months 2191 729 365 Long-Only Trade Strategy for ^IXIC No long ^IXIC 2008-01-03 2008-12-31 1.0 -0.4 -0.4 -1.02 -0.49 0.12 -0.09
37 2 6 Months 2464 821 364 ts_gru_1_^IXIC No ts_gru_1 ^IXIC 2009-01-05 2009-12-31 1.0 0.18 0.18 0.71 -0.19 0.07 -0.07
38 2 6 Months 2464 821 364 ts_lstm_^IXIC No ts_lstm ^IXIC 2009-01-05 2009-12-31 1.0 -0.0 -0.0 0.13 -0.25 0.07 -0.04
39 2 6 Months 2464 821 364 ts_conv1d_gru_^IXIC No ts_conv1d_gru ^IXIC 2009-01-05 2009-12-31 1.0 0.04 0.05 0.3 -0.2 0.07 -0.04
40 2 6 Months 2464 821 364 ts_gru_2_^IXIC No ts_gru_2 ^IXIC 2009-01-05 2009-12-31 1.0 0.12 0.12 0.53 -0.17 0.07 -0.06
41 2 6 Months 2464 821 364 ts_sma_2_^IXIC No ts_sma_2 ^IXIC 2009-01-05 2009-12-31 0.99 0.27 0.27 0.99 -0.21 0.05 -0.07
42 2 6 Months 2464 821 364 ts_kama_^IXIC No ts_kama ^IXIC 2009-01-05 2009-12-31 1.0 0.31 0.32 1.2 -0.21 0.05 -0.05
43 2 6 Months 2464 821 364 ts_tsi_^IXIC No ts_tsi ^IXIC 2009-01-05 2009-12-31 0.97 -0.05 -0.05 -0.06 -0.23 0.07 -0.05
44 2 6 Months 2464 821 364 all_^IXIC No all ^IXIC 2009-01-05 2009-12-31 1.0 0.19 0.19 0.74 -0.19 0.07 -0.07
53 2 6 Months 2464 821 364 Long-Only Trade Strategy for ^IXIC No long ^IXIC 2009-01-05 2009-12-31 1.0 0.39 0.4 1.32 -0.23 0.07 -0.06
65 3 6 Months 2737 913 364 ts_gru_1_^IXIC No ts_gru_1 ^IXIC 2010-01-05 2010-12-31 1.0 -0.13 -0.13 -0.59 -0.25 0.05 -0.04
66 3 6 Months 2737 913 364 ts_lstm_^IXIC No ts_lstm ^IXIC 2010-01-05 2010-12-31 1.0 -0.12 -0.12 -0.53 -0.24 0.05 -0.04
67 3 6 Months 2737 913 364 ts_conv1d_gru_^IXIC No ts_conv1d_gru ^IXIC 2010-01-05 2010-12-31 1.0 -0.12 -0.12 -0.53 -0.23 0.05 -0.04
68 3 6 Months 2737 913 364 ts_gru_2_^IXIC No ts_gru_2 ^IXIC 2010-01-05 2010-12-31 1.0 -0.19 -0.2 -0.98 -0.28 0.05 -0.04
69 3 6 Months 2737 913 364 ts_sma_2_^IXIC No ts_sma_2 ^IXIC 2010-01-05 2010-12-31 0.98 -0.2 -0.2 -1.08 -0.31 0.05 -0.04
70 3 6 Months 2737 913 364 ts_kama_^IXIC No ts_kama ^IXIC 2010-01-05 2010-12-31 1.0 -0.06 -0.06 -0.2 -0.18 0.05 -0.04
71 3 6 Months 2737 913 364 ts_tsi_^IXIC No ts_tsi ^IXIC 2010-01-05 2010-12-31 0.96 0.06 0.06 0.38 -0.19 0.04 -0.05
72 3 6 Months 2737 913 364 all_^IXIC No all ^IXIC 2010-01-05 2010-12-31 1.0 -0.08 -0.08 -0.33 -0.18 0.05 -0.04
81 3 6 Months 2737 913 364 Long-Only Trade Strategy for ^IXIC No long ^IXIC 2010-01-05 2010-12-31 1.0 0.15 0.15 0.81 -0.17 0.05 -0.04
93 4 6 Months 3011 1003 364 ts_gru_1_^IXIC No ts_gru_1 ^IXIC 2011-01-04 2011-12-30 1.0 -0.03 -0.03 0.0 -0.27 0.05 -0.07
94 4 6 Months 3011 1003 364 ts_lstm_^IXIC No ts_lstm ^IXIC 2011-01-04 2011-12-30 1.0 0.13 0.13 0.61 -0.19 0.05 -0.07
95 4 6 Months 3011 1003 364 ts_conv1d_gru_^IXIC No ts_conv1d_gru ^IXIC 2011-01-04 2011-12-30 1.0 0.1 0.1 0.49 -0.23 0.05 -0.07
96 4 6 Months 3011 1003 364 ts_gru_2_^IXIC No ts_gru_2 ^IXIC 2011-01-04 2011-12-30 1.0 -0.03 -0.03 0.0 -0.24 0.05 -0.07
97 4 6 Months 3011 1003 364 ts_sma_2_^IXIC No ts_sma_2 ^IXIC 2011-01-04 2011-12-30 0.97 -0.24 -0.24 -0.99 -0.37 0.05 -0.07
98 4 6 Months 3011 1003 364 ts_kama_^IXIC No ts_kama ^IXIC 2011-01-04 2011-12-30 1.0 -0.22 -0.22 -0.86 -0.31 0.07 -0.05
99 4 6 Months 3011 1003 364 ts_tsi_^IXIC No ts_tsi ^IXIC 2011-01-04 2011-12-30 0.94 -0.17 -0.17 -0.68 -0.26 0.06 -0.04
100 4 6 Months 3011 1003 364 all_^IXIC No all ^IXIC 2011-01-04 2011-12-30 1.0 -0.08 -0.08 -0.19 -0.26 0.05 -0.07
109 4 6 Months 3011 1003 364 Long-Only Trade Strategy for ^IXIC No long ^IXIC 2011-01-04 2011-12-30 1.0 -0.03 -0.03 -0.0 -0.19 0.05 -0.07
121 5 6 Months 3286 1093 365 ts_gru_1_^IXIC No ts_gru_1 ^IXIC 2012-01-04 2012-12-31 1.0 -0.17 -0.17 -1.14 -0.2 0.03 -0.03
122 5 6 Months 3286 1093 365 ts_lstm_^IXIC No ts_lstm ^IXIC 2012-01-04 2012-12-31 1.0 -0.08 -0.08 -0.5 -0.15 0.03 -0.03
123 5 6 Months 3286 1093 365 ts_conv1d_gru_^IXIC No ts_conv1d_gru ^IXIC 2012-01-04 2012-12-31 1.0 -0.17 -0.17 -1.15 -0.18 0.03 -0.03
124 5 6 Months 3286 1093 365 ts_gru_2_^IXIC No ts_gru_2 ^IXIC 2012-01-04 2012-12-31 1.0 -0.1 -0.1 -0.61 -0.15 0.03 -0.03
125 5 6 Months 3286 1093 365 ts_sma_2_^IXIC No ts_sma_2 ^IXIC 2012-01-04 2012-12-31 0.98 0.09 0.09 0.7 -0.08 0.03 -0.03
126 5 6 Months 3286 1093 365 ts_kama_^IXIC No ts_kama ^IXIC 2012-01-04 2012-12-31 1.0 -0.02 -0.02 -0.08 -0.13 0.03 -0.03
127 5 6 Months 3286 1093 365 ts_tsi_^IXIC No ts_tsi ^IXIC 2012-01-04 2012-12-31 0.95 0.07 0.07 0.54 -0.14 0.03 -0.02
128 5 6 Months 3286 1093 365 all_^IXIC No all ^IXIC 2012-01-04 2012-12-31 1.0 -0.07 -0.07 -0.42 -0.13 0.03 -0.03
137 5 6 Months 3286 1093 365 Long-Only Trade Strategy for ^IXIC No long ^IXIC 2012-01-04 2012-12-31 1.0 0.14 0.14 0.96 -0.12 0.03 -0.03
S&P 500
In [78]:
tsExecuteEngine.getSummaryMetrics()\
[ [ 'wfa_sw_iter_no', 'wfa_slide_win_size', 'wfa_slide_win_period', 'tr_period_len_days', 'val_period_len_days',
    'test_period_len_days', 'ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 
    'Start Period', 'End Period', 'Time in Market ',
    'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^GSPC" ')
Out[78]:
wfa_sw_iter_no wfa_slide_win_size wfa_slide_win_period tr_period_len_days val_period_len_days test_period_len_days ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
17 1 6 Months 2191 729 365 ts_gru_1_^GSPC No ts_gru_1 ^GSPC 2008-01-03 2008-12-31 1.0 0.37 0.37 0.97 -0.25 0.12 -0.09
18 1 6 Months 2191 729 365 ts_lstm_^GSPC No ts_lstm ^GSPC 2008-01-03 2008-12-31 1.0 -0.18 -0.18 -0.26 -0.43 0.12 -0.09
19 1 6 Months 2191 729 365 ts_conv1d_gru_^GSPC No ts_conv1d_gru ^GSPC 2008-01-03 2008-12-31 1.0 0.48 0.48 1.15 -0.27 0.12 -0.09
20 1 6 Months 2191 729 365 ts_gru_2_^GSPC No ts_gru_2 ^GSPC 2008-01-03 2008-12-31 1.0 0.62 0.63 1.38 -0.25 0.12 -0.09
21 1 6 Months 2191 729 365 ts_sma_2_^GSPC No ts_sma_2 ^GSPC 2008-01-03 2008-12-31 0.99 0.42 0.42 1.46 -0.08 0.07 -0.06
22 1 6 Months 2191 729 365 ts_kama_^GSPC No ts_kama ^GSPC 2008-01-03 2008-12-31 1.0 0.38 0.38 1.44 -0.09 0.06 -0.05
23 1 6 Months 2191 729 365 ts_tsi_^GSPC No ts_tsi ^GSPC 2008-01-03 2008-12-31 0.91 0.02 0.02 0.23 -0.19 0.08 -0.07
24 1 6 Months 2191 729 365 all_^GSPC No all ^GSPC 2008-01-03 2008-12-31 1.0 1.16 1.17 2.07 -0.19 0.12 -0.08
27 1 6 Months 2191 729 365 Long-Only Trade Strategy for ^GSPC No long ^GSPC 2008-01-03 2008-12-31 1.0 -0.38 -0.38 -0.94 -0.48 0.12 -0.09
45 2 6 Months 2464 821 364 ts_gru_1_^GSPC No ts_gru_1 ^GSPC 2009-01-05 2009-12-31 1.0 0.42 0.43 1.43 -0.14 0.07 -0.05
46 2 6 Months 2464 821 364 ts_lstm_^GSPC No ts_lstm ^GSPC 2009-01-05 2009-12-31 1.0 0.26 0.27 1.0 -0.26 0.07 -0.05
47 2 6 Months 2464 821 364 ts_conv1d_gru_^GSPC No ts_conv1d_gru ^GSPC 2009-01-05 2009-12-31 1.0 0.42 0.43 1.44 -0.19 0.07 -0.05
48 2 6 Months 2464 821 364 ts_gru_2_^GSPC No ts_gru_2 ^GSPC 2009-01-05 2009-12-31 1.0 0.86 0.87 2.44 -0.15 0.07 -0.05
49 2 6 Months 2464 821 364 ts_sma_2_^GSPC No ts_sma_2 ^GSPC 2009-01-05 2009-12-31 0.98 0.25 0.26 1.03 -0.19 0.05 -0.06
50 2 6 Months 2464 821 364 ts_kama_^GSPC No ts_kama ^GSPC 2009-01-05 2009-12-31 1.0 0.27 0.27 1.15 -0.22 0.04 -0.05
51 2 6 Months 2464 821 364 ts_tsi_^GSPC No ts_tsi ^GSPC 2009-01-05 2009-12-31 0.97 0.08 0.08 0.42 -0.15 0.07 -0.04
52 2 6 Months 2464 821 364 all_^GSPC No all ^GSPC 2009-01-05 2009-12-31 1.0 0.46 0.47 1.54 -0.12 0.07 -0.05
55 2 6 Months 2464 821 364 Long-Only Trade Strategy for ^GSPC No long ^GSPC 2009-01-05 2009-12-31 1.0 0.2 0.2 0.8 -0.28 0.07 -0.05
73 3 6 Months 2737 913 364 ts_gru_1_^GSPC No ts_gru_1 ^GSPC 2010-01-05 2010-12-31 1.0 0.09 0.09 0.55 -0.15 0.04 -0.04
74 3 6 Months 2737 913 364 ts_lstm_^GSPC No ts_lstm ^GSPC 2010-01-05 2010-12-31 1.0 -0.06 -0.06 -0.25 -0.19 0.04 -0.04
75 3 6 Months 2737 913 364 ts_conv1d_gru_^GSPC No ts_conv1d_gru ^GSPC 2010-01-05 2010-12-31 1.0 -0.11 -0.11 -0.54 -0.2 0.04 -0.04
76 3 6 Months 2737 913 364 ts_gru_2_^GSPC No ts_gru_2 ^GSPC 2010-01-05 2010-12-31 1.0 -0.04 -0.04 -0.15 -0.18 0.04 -0.04
77 3 6 Months 2737 913 364 ts_sma_2_^GSPC No ts_sma_2 ^GSPC 2010-01-05 2010-12-31 0.98 -0.15 -0.15 -0.83 -0.25 0.04 -0.03
78 3 6 Months 2737 913 364 ts_kama_^GSPC No ts_kama ^GSPC 2010-01-05 2010-12-31 1.0 0.02 0.02 0.2 -0.15 0.04 -0.04
79 3 6 Months 2737 913 364 ts_tsi_^GSPC No ts_tsi ^GSPC 2010-01-05 2010-12-31 0.95 0.01 0.01 0.14 -0.15 0.04 -0.04
80 3 6 Months 2737 913 364 all_^GSPC No all ^GSPC 2010-01-05 2010-12-31 1.0 -0.06 -0.06 -0.25 -0.2 0.04 -0.04
83 3 6 Months 2737 913 364 Long-Only Trade Strategy for ^GSPC No long ^GSPC 2010-01-05 2010-12-31 1.0 0.11 0.11 0.67 -0.16 0.04 -0.04
101 4 6 Months 3011 1003 364 ts_gru_1_^GSPC No ts_gru_1 ^GSPC 2011-01-04 2011-12-30 1.0 -0.09 -0.09 -0.28 -0.22 0.05 -0.07
102 4 6 Months 3011 1003 364 ts_lstm_^GSPC No ts_lstm ^GSPC 2011-01-04 2011-12-30 1.0 0.03 0.03 0.24 -0.15 0.05 -0.07
103 4 6 Months 3011 1003 364 ts_conv1d_gru_^GSPC No ts_conv1d_gru ^GSPC 2011-01-04 2011-12-30 1.0 0.11 0.11 0.55 -0.13 0.05 -0.07
104 4 6 Months 3011 1003 364 ts_gru_2_^GSPC No ts_gru_2 ^GSPC 2011-01-04 2011-12-30 1.0 -0.09 -0.09 -0.28 -0.26 0.05 -0.07
105 4 6 Months 3011 1003 364 ts_sma_2_^GSPC No ts_sma_2 ^GSPC 2011-01-04 2011-12-30 0.98 -0.11 -0.11 -0.43 -0.23 0.07 -0.04
106 4 6 Months 3011 1003 364 ts_kama_^GSPC No ts_kama ^GSPC 2011-01-04 2011-12-30 1.0 0.03 0.03 0.25 -0.13 0.06 -0.04
107 4 6 Months 3011 1003 364 ts_tsi_^GSPC No ts_tsi ^GSPC 2011-01-04 2011-12-30 0.94 -0.15 -0.15 -0.67 -0.22 0.06 -0.04
108 4 6 Months 3011 1003 364 all_^GSPC No all ^GSPC 2011-01-04 2011-12-30 1.0 -0.05 -0.05 -0.11 -0.19 0.05 -0.07
111 4 6 Months 3011 1003 364 Long-Only Trade Strategy for ^GSPC No long ^GSPC 2011-01-04 2011-12-30 1.0 -0.01 -0.01 0.07 -0.19 0.05 -0.07
129 5 6 Months 3286 1093 365 ts_gru_1_^GSPC No ts_gru_1 ^GSPC 2012-01-04 2012-12-31 1.0 -0.15 -0.16 -1.27 -0.19 0.02 -0.02
130 5 6 Months 3286 1093 365 ts_lstm_^GSPC No ts_lstm ^GSPC 2012-01-04 2012-12-31 1.0 -0.06 -0.06 -0.43 -0.15 0.02 -0.02
131 5 6 Months 3286 1093 365 ts_conv1d_gru_^GSPC No ts_conv1d_gru ^GSPC 2012-01-04 2012-12-31 1.0 0.19 0.19 1.46 -0.09 0.02 -0.02
132 5 6 Months 3286 1093 365 ts_gru_2_^GSPC No ts_gru_2 ^GSPC 2012-01-04 2012-12-31 1.0 -0.07 -0.08 -0.54 -0.12 0.02 -0.03
133 5 6 Months 3286 1093 365 ts_sma_2_^GSPC No ts_sma_2 ^GSPC 2012-01-04 2012-12-31 0.98 0.08 0.08 0.68 -0.08 0.02 -0.02
134 5 6 Months 3286 1093 365 ts_kama_^GSPC No ts_kama ^GSPC 2012-01-04 2012-12-31 0.99 -0.11 -0.11 -0.84 -0.21 0.02 -0.03
135 5 6 Months 3286 1093 365 ts_tsi_^GSPC No ts_tsi ^GSPC 2012-01-04 2012-12-31 0.95 -0.04 -0.04 -0.28 -0.14 0.02 -0.02
136 5 6 Months 3286 1093 365 all_^GSPC No all ^GSPC 2012-01-04 2012-12-31 1.0 -0.06 -0.06 -0.45 -0.18 0.02 -0.03
139 5 6 Months 3286 1093 365 Long-Only Trade Strategy for ^GSPC No long ^GSPC 2012-01-04 2012-12-31 1.0 0.12 0.12 0.94 -0.1 0.02 -0.02

Persist Backtest to DB (optional )

In [ ]:
session.add( tsExecuteEngine )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst)
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")
In [ ]:
 

Reports

The reports currently supported are provided by quantstats, https://github.com/ranaroussi/quantstats.

  • Guidelines:
    1. Run a backtest (Backtest, WFA Backtest )
    2. Select the Report to execute
    3. Select a trade strategy from the backtest for the report
    4. Optional, select a trade strategy from the backtest to use as a benchmark for the report
In [166]:
from trade_engine.reports.BacktestReports import BacktestReports

WFA-Backtest for Reports

Description:

  • Portfolio has a subset of the trade strategies in Portfolio G
    • Smaller subset of TA and AI models to reduce execution duration
  • This WFA-Backtest is similar to WFA-Backtest 3, except for:
    • the length of
    • the Traning and Validation periods are reduced by 1/3 duration
    • Re-fit AI trading models every 3 months
    • Training-set is not anchored

Backtest:

1. Type: WFA Backtest
2. AI Models Fit Date Ranges
    1. Training Period: 
        1. Begin Date = 2008-05-01 
        2. End Date   = 2010-04-30  
    2. Validation Period: 
        1. Begin Date = 2010-05-01 
        2. End Date   = 2010-12-31   
4. Test Period: 
    1. Begin Date = 2011-01-01 
    2. End Date   = 2012-12-31  

Portfolio Trade Assets

In [110]:
portfolio_trade_assets   = [ "^DJI", "^IXIC", "^GSPC" ]

Market Data Manager

In [111]:
dirPathMarketData = '/Users/gustavozambrana/Google Drive/Python/Projects/Trade_Engine/Data/US_Market_Indixes'

supportedTradeAssets   = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str           = "1980-01-01"
end_date_str           = None

ts_marketdat_mng = TradeStrategyMarketDataMng(\
        marketDataProviderName = "yahoofinance",
        supportedTradeAssets   = supportedTradeAssets,
        stock_price_col_name   = "Adj Close",
        fileNameMarketData     = "US_Indixes_And_ETFs_MrkData_From_1980",
        dirPathMarketData      = dirPathMarketData,
        beg_date_str           = beg_date_str,
        end_date_str           = end_date_str,
        interval               = "1d"  ) 
2021-10-30 23:36:10,769 [INFO] root: Found previous Market data previously loaded to specified file and dir.

Pipeline Data Manager

In [112]:
ts_model_pipline_mng_g = TradeStrategyModelPipelineDataMng(\
                            tsMarketDataMng    = ts_marketdat_mng,
                            package            = "trade_engine.model.ai.WaveNet_RNN_AI_PipelineBuilder",
                            model_class_name   = "WaveNet_RNN_AI_PipelineBuilder",
                            fileNameMarketData = "WaveNet_RNN_AI_Pipeline_Data_Portf_G",
                            forceCreatePipelineData = True,
                            dirPathMarketData  = dirPathMarketData )

Simulation Broker

In [113]:
brokerTradingObj = SimBrokerTrading()

Trade Strategies, Trade Investment Manager, and Trade Asset Register Items

In [114]:
tsConfDat = TradeStrategyConfigData()

# Set Config

tsConfDat.tsSetConfig(\
    ts_set_conf_dict = 
           { 'set_actions_conf' : 
                      { "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
                        "exit"  : { 'votingPolicy' : 1, 
                                    'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
                                    'lastn_match' : 1 } 
                      }
           } )
           
# TS #1

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_gru_1", 
    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "gru",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'         : 20 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 1, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 } },

                               "stop_lost" :
                                    { 'model'    : "fix_perc",
                                      'type'     : "ta",
                                      'obj_args' : { 'long_stop_los_per' : 5, 'short_stop_los_per'    : 5 }  } 
                             },
                    }  )

# TS #2

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_lstm", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "lstm",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'         : 50,   'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn'   : True,
                                                 'epochs'          : 20 }  
                                }
                            } }  )
# TS #3
    
tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_conv1d_gru", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "conv1d_gru",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'   : 50,   'no_neurons_lay1'    : 20,
                                                 'no_neurons_lay2' : 20,   'pred_ahead_periods' : 5,
                                                 'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                                 'epochs'          : 20 }  
                                }
                            } }  )

# TS #8
tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_gru_2", 
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "gru",
                                  'type'     : "ai",
                                  'obj_args' : { 'n_steps'          : 40,   'no_neurons_lay1'    : 20,
                                         'no_neurons_lay2' : 20,   'pred_ahead_periods' : 3,
                                         'ext_trade_dyn'   : True, 're_eval_exit_dyn' : True,
                                         'epochs'          : 20 }  
                                }
                            } }  )

# TS #10

tsConfDat.addTSConf(\
   ts_conf_dict = { 
          'ts_unique_tag' : "ts_sma_2",    
          'actions_conf'  : { "entry_exit" :  
                                { 'model'    : "sma",
                                  'type'     : "ta",
                                  'obj_args' : { 'win_fast' : 15, 'win_slow' : 60 } ,
                                  'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                                  'exit_policy_args'   : { 'lastn_match' : 1 },
                                },
                            }  } )

# TS #16

tsConfDat.addTSConf(\
   ts_conf_dict = { 
      'ts_unique_tag' : "ts_kama",    
      'actions_conf'  : { "entry_exit" :  
                            { 'model'    : "kama",
                              'type'     : "ta",
                              'obj_args' : { 'window_fast' : 10, 'pow1_fast' : 2, 'pow2_fast'  : 30,
                                             'window_slow' : 10, 'pow1_slow' : 5, 'pow2_slow'  : 30 },
                              'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                              'exit_policy_args'   : { 'lastn_match' : 1 },
                            },
                        }  } )
# TS #17

tsConfDat.addTSConf(\
   ts_conf_dict = { 
      'ts_unique_tag' : "ts_tsi",    
      'actions_conf'  : { "entry_exit" :  
                            { 'model'    : "tsi",
                              'type'     : "ta",
                              'obj_args' : { 'window_slow' : 25, 'window_fast' : 5 },
                              'entry_policy_args'  : { 'lastn_match' : 2, 'cross_enter_signal' : False },
                              'exit_policy_args'   : { 'lastn_match' : 1 },
                            },
                        }  } )
In [115]:
taRegisterItems = [ ]
tsActionGen = TradeStrategyActionGenerator()

for trade_asset in portfolio_trade_assets :
    
    num_ts = len(tsConfDat.name_list) + 1  # adding the composite  trade strategy
    
    for i in range( num_ts ) :

        if i <= num_ts - 2:
            # *** Trade Strategy 

            actionDatItem  = tsConfDat.getTSConfigDataForItem(item_num = i )
            ts_unique_name = actionDatItem.name_list[0]
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = actionDatItem,
                                                     pipelineMng       = ts_model_pipline_mng_g )
        else :
            # Composite Trade Strategy 
            
            ts_unique_name = "all"            
            trade_enter_set, trade_exit_set = tsActionGen.createEnterAndExitActionObjs ( \
                                                     ts_marketdat_mng  = ts_marketdat_mng, 
                                                     test_trade_asset  = trade_asset, 
                                                     dirPathMarketData = dirPathMarketData,
                                                     actionData        = tsConfDat,
                                                     pipelineMng       = ts_model_pipline_mng_g )

        ts_model = TradeStrategyBaseModelPersist(\
                        trade_asset               = trade_asset,
                        ts_marketdat_mng          = ts_marketdat_mng,
                        ts_enter                  = trade_enter_set,
                        ts_exit                   = trade_exit_set,                       
                        model_type                = ts_unique_name,
                        model_version             = "1.0",
                        market_data_period        = MarketDataPeriod.Day,
                    ) 

        # *** Trade Strategy Investment Manager 

        taInvMng = TradingAssetInvMngBase(\
                                        trade_asset                = trade_asset,
                                        minPeriodsBetweenTrades    = 1,
                                        initInvestment             = 1000000.0, 
                                        capPercentToInvestPerTrade = 100.0,
                                        minInvestPercent           = 5.0,
                                        min_account_balance        = 1000.0 )

        # *** Trade Register Item
        # *** This object has all configuration defined to execute a given trade strategy,
        # *** It can be executed individually in backtest or as part of a portfolio

        ta_registered_item = TradingAssetRegisterItem(\
                trade_name                    = "{0}_{1}".format(ts_unique_name, trade_asset), 
                ts_model                      = ts_model,
                tradingExecutionType          = TradingAssetExecutionType.Simulation,
                tradingBrokerObj              = brokerTradingObj,
                tradingAssetInvMngObj         = taInvMng )  

        taRegisterItems.append(ta_registered_item)
In [116]:
print("Number of configured Trade Asset Register Items: ", len(taRegisterItems) )
Number of configured Trade Asset Register Items:  24

Portfolio Investment Manager

In [117]:
# *** Porttfolio Investment Manager across all individual trade strategies investment managers
# *** Role: 
# ***    1) Managed investment funds across n number of trade strategies
# ***    2) Rebalance portfolio periodically or never
# ***    3) Portfolio Policy Weights 
# ***          equal weights (default)
# ***          MinimumVariance
# ***          User defined 
# ***    4) Track Portfolio level returns and metrics
# ***          Individual Trade Strategies return and metrics tracked through their 
# ***          investment managers
# ***          Portfolio funds are split across each trade strategy investment manager based on the
# ***          portfolio weights

portfInvMng = PortfolioInvMng(\
                  name                       = "Portfolio Inv. Manager for US-Indexes - TechAnal & AI Trading Models TS",
                  initInvestment             = 2000000.0 * ( len(taRegisterItems) + 3),  # 200K/trade-strag
                  portfRebalanceFreq         = PortfolioRebalanceFrequency.Never,
                  portfRebalancePeriods      = 1,
                  minInvestPercent           = 5.0,
                  min_account_balance        = 1000.0,     
                  minPeriodsBetweenTrades    = 1,
                  capPercentToInvestPerTrade = 100.0 )

Trade Register Items Portfolio

In [118]:
# *** Set of Trade Register Items
#
# Configuration Summary:
#    - Each set has 1 to n trade register items as previously described 
#    - Optionally add long only trade strategies for all unique trade assets in the
#      portfolio 
#           - (Dow, Nasdaq, and S&P 500 for this portfolio) in this example
#           - Might be useful for bench marking trade strategies
#    - Each set has one Investment Portfolio Manager
#       - portfolio funds allocated per portfolio policy rules and re-balanced (if defined), 
#         across all trade strategies


portf_registered_obj = PortfolioRegisterItem(\
                        name                 = "Portfolio of US-Indexes with TechAnal & AI Trading Models, and Long strategies",
                        taRegisterItems      = taRegisterItems,
                        portfolioInvMngObj   = portfInvMng,
                        tradingExecutionType = TradingAssetExecutionType.Simulation,
                        add_long_only_ts     = True )
2021-10-30 23:36:38,106 [INFO] root: *** Adding long only trade strategies for : {'^IXIC', '^DJI', '^GSPC'}

Training, Validation and Test Periods for Backtest

In Order to backtest a trade strategy or portfolio that has AI models, the following data is required:

  1. Training Date Range

    1. Date range that will be used to train the AI models in the backtest
  2. Validation Date Range

    1. Date range that twill be used to validate the AI models, should not overlapped with the training date range
  3. Test Period Date Range

    1. This is the out-sample date range, which corresponds to the date range of the backtest

Date Ranges are defined with a DatasetDef object, and have the following parameters:

  1. strBegDateAIModels : Date to begin training or validation of an AI model
  2. strBegDate : Date to begin the backtest
  3. strEndDate : Date to end training, validation and Backtest

Note:

  1. The param strBegDateAIModels can be defined as the same date as strBegDate, that is the default, if not defined.
  2. The critical aspect of using this parameter is in the backtest. Some AI Models, such as time series, others using moving averages over many periods, create params with no predicting data for those initial dates. Thus, in order to ensure the backtest starts on the actual date specified, the strBegDateAIModels should be defined as an earlier date, and it should not overlapped with the validation period end-date to avoid any chance of bias by picking at the validation data.
In [119]:
training_period = DatasetDef(datasetType = DatasetType.Training,
                             strBegDateAIModels = "2007-11-01",
                             strBegDate         = "2008-05-01",
                             strEndDate         = "2010-04-30" )

validation_period = DatasetDef(datasetType = DatasetType.Validation,
                               strBegDateAIModels = "2009-11-01",
                               strBegDate         = "2010-05-01",
                               strEndDate         = "2010-12-31" )

testing_period = DatasetDef(datasetType = DatasetType.Testing,
                               strBegDateAIModels = "2010-07-01",
                               strBegDate         = "2011-01-01",
                               strEndDate         = "2012-12-31" )

fit_datasets = FitDatasetsDef( trainingDataset    = training_period,
                               validationDataset  = validation_period )

Execute WFA Backtest

In [120]:
tsExecuteEngine = BacktestExecutionWFA( \
            name                        = "WFA Backtest-4 for subset of Portfolio G - anchored training-set",
            test_period                 = testing_period,
            fit_datasets_start          = fit_datasets,
            trade_asset_registered_item = portf_registered_obj,
            wfa_slide_win_size          = 3,
            wfa_slide_win_period        = WFASlideWindowPeriod.Months, 
            anchor_fit_dataset          = False )                      
In [ ]:
tsExecuteEngine.evaluate()

Backtest Metrics

Trade Strategies Execution & Investment Metrics

DOW Jones

In [122]:
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
        'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
        query('TA_Reg_Name.str.contains("DJI")', engine='python')
Out[122]:
TA_Reg_Name Is_Portfolio Num_Trades_Completed Init_Capital Final_Capital Cum_Return Backtest_Status
1 ts_gru_1_^DJI No 94 2000000.0 2.409690e+06 0.204845 Completed
2 ts_lstm_^DJI No 67 2000000.0 2.531228e+06 0.265614 Completed
3 ts_conv1d_gru_^DJI No 89 2000000.0 2.360190e+06 0.180095 Completed
4 ts_gru_2_^DJI No 144 2000000.0 1.890071e+06 -0.054964 Completed
5 ts_sma_2_^DJI No 11 2000000.0 1.841726e+06 -0.079137 Completed
6 ts_kama_^DJI No 8 2000000.0 1.988360e+06 -0.005820 Completed
7 ts_tsi_^DJI No 26 2000000.0 1.758361e+06 -0.120820 Completed
8 all_^DJI No 92 2000000.0 2.366672e+06 0.183336 Completed
26 Long-Only Trade Strategy for ^DJI No 1 2000000.0 2.245110e+06 0.122555 Completed

Nasdaq

In [123]:
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
        'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
        query('TA_Reg_Name.str.contains("IXIC")', engine='python')
Out[123]:
TA_Reg_Name Is_Portfolio Num_Trades_Completed Init_Capital Final_Capital Cum_Return Backtest_Status
9 ts_gru_1_^IXIC No 124 2000000.0 2.126741e+06 0.063371 Completed
10 ts_lstm_^IXIC No 80 2000000.0 3.885654e+06 0.942827 Completed
11 ts_conv1d_gru_^IXIC No 91 2000000.0 3.330966e+06 0.665483 Completed
12 ts_gru_2_^IXIC No 148 2000000.0 2.013696e+06 0.006848 Completed
13 ts_sma_2_^IXIC No 16 2000000.0 1.640432e+06 -0.179784 Completed
14 ts_kama_^IXIC No 11 2000000.0 1.496984e+06 -0.251508 Completed
15 ts_tsi_^IXIC No 25 2000000.0 1.806895e+06 -0.096552 Completed
16 all_^IXIC No 107 2000000.0 2.568200e+06 0.284100 Completed
25 Long-Only Trade Strategy for ^IXIC No 1 2000000.0 2.243697e+06 0.121848 Completed

S&P 500

In [124]:
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
        'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
        query('TA_Reg_Name.str.contains("GSPC")', engine='python')
Out[124]:
TA_Reg_Name Is_Portfolio Num_Trades_Completed Init_Capital Final_Capital Cum_Return Backtest_Status
17 ts_gru_1_^GSPC No 110 2000000.0 2.180504e+06 0.090252 Completed
18 ts_lstm_^GSPC No 57 2000000.0 2.503388e+06 0.251694 Completed
19 ts_conv1d_gru_^GSPC No 102 2000000.0 2.625871e+06 0.312935 Completed
20 ts_gru_2_^GSPC No 122 2000000.0 2.002088e+06 0.001044 Completed
21 ts_sma_2_^GSPC No 12 2000000.0 1.942915e+06 -0.028543 Completed
22 ts_kama_^GSPC No 8 2000000.0 1.809392e+06 -0.095304 Completed
23 ts_tsi_^GSPC No 27 2000000.0 1.653393e+06 -0.173303 Completed
24 all_^GSPC No 83 2000000.0 1.958139e+06 -0.020930 Completed
27 Long-Only Trade Strategy for ^GSPC No 1 2000000.0 2.242591e+06 0.121295 Completed
Performance Metrics

Dow Jones

In [125]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
        query('trade_asset == "^DJI" ')
Out[125]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
1 ts_gru_1_^DJI No ts_gru_1 ^DJI 2011-01-04 2012-12-31 1.0 0.2 0.1 0.63 -0.14 0.05 -0.06
2 ts_lstm_^DJI No ts_lstm ^DJI 2011-01-04 2012-12-31 1.0 0.27 0.13 0.78 -0.18 0.04 -0.06
3 ts_conv1d_gru_^DJI No ts_conv1d_gru ^DJI 2011-01-04 2012-12-31 1.0 0.18 0.09 0.57 -0.17 0.04 -0.06
4 ts_gru_2_^DJI No ts_gru_2 ^DJI 2011-01-04 2012-12-31 1.0 -0.05 -0.03 -0.08 -0.19 0.05 -0.06
5 ts_sma_2_^DJI No ts_sma_2 ^DJI 2011-01-04 2012-12-31 0.99 -0.08 -0.04 -0.17 -0.24 0.06 -0.04
6 ts_kama_^DJI No ts_kama ^DJI 2011-01-04 2012-12-31 1.0 -0.01 -0.0 0.06 -0.16 0.05 -0.04
7 ts_tsi_^DJI No ts_tsi ^DJI 2011-01-04 2012-12-31 0.94 -0.12 -0.06 -0.34 -0.21 0.05 -0.04
8 all_^DJI No all ^DJI 2011-01-04 2012-12-31 1.0 0.18 0.09 0.58 -0.2 0.05 -0.06
26 Long-Only Trade Strategy for ^DJI No long ^DJI 2011-01-04 2012-12-31 1.0 0.12 0.06 0.43 -0.17 0.04 -0.06
In [ ]:
tsExecuteEngine.getSummaryMetrics().query('trade_asset == "^DJI" ').T.head(60)

Nasdaq

In [126]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
        query('trade_asset == "^IXIC" ')
Out[126]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
9 ts_gru_1_^IXIC No ts_gru_1 ^IXIC 2011-01-04 2012-12-31 1.0 0.06 0.03 0.25 -0.28 0.05 -0.07
10 ts_lstm_^IXIC No ts_lstm ^IXIC 2011-01-04 2012-12-31 1.0 0.94 0.4 1.72 -0.17 0.05 -0.07
11 ts_conv1d_gru_^IXIC No ts_conv1d_gru ^IXIC 2011-01-04 2012-12-31 1.0 0.67 0.29 1.34 -0.19 0.05 -0.07
12 ts_gru_2_^IXIC No ts_gru_2 ^IXIC 2011-01-04 2012-12-31 1.0 0.01 0.0 0.12 -0.24 0.05 -0.07
13 ts_sma_2_^IXIC No ts_sma_2 ^IXIC 2011-01-04 2012-12-31 0.97 -0.18 -0.09 -0.39 -0.37 0.05 -0.07
14 ts_kama_^IXIC No ts_kama ^IXIC 2011-01-04 2012-12-31 1.0 -0.25 -0.14 -0.61 -0.31 0.07 -0.05
15 ts_tsi_^IXIC No ts_tsi ^IXIC 2011-01-04 2012-12-31 0.95 -0.1 -0.05 -0.17 -0.26 0.06 -0.04
16 all_^IXIC No all ^IXIC 2011-01-04 2012-12-31 1.0 0.28 0.13 0.7 -0.22 0.05 -0.07
25 Long-Only Trade Strategy for ^IXIC No long ^IXIC 2011-01-04 2012-12-31 1.0 0.12 0.06 0.38 -0.19 0.05 -0.07
In [ ]:
tsExecuteEngine.getSummaryMetrics().query('trade_asset == "^IXIC" ').T.head(60)

S&P 500

In [127]:
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
   'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
        query('trade_asset == "^GSPC" ')
Out[127]:
ta_reg_item_name is_portfolio model_type trade_asset Start Period End Period Time in Market Cumulative Return CAGR% Sharpe Max Drawdown Best Day Worst Day
17 ts_gru_1_^GSPC No ts_gru_1 ^GSPC 2011-01-04 2012-12-31 1.0 0.09 0.04 0.32 -0.2 0.05 -0.07
18 ts_lstm_^GSPC No ts_lstm ^GSPC 2011-01-04 2012-12-31 1.0 0.25 0.12 0.69 -0.17 0.05 -0.07
19 ts_conv1d_gru_^GSPC No ts_conv1d_gru ^GSPC 2011-01-04 2012-12-31 1.0 0.31 0.15 0.81 -0.18 0.05 -0.07
20 ts_gru_2_^GSPC No ts_gru_2 ^GSPC 2011-01-04 2012-12-31 1.0 0.0 0.0 0.1 -0.22 0.05 -0.07
21 ts_sma_2_^GSPC No ts_sma_2 ^GSPC 2011-01-04 2012-12-31 0.98 -0.03 -0.01 0.01 -0.23 0.07 -0.04
22 ts_kama_^GSPC No ts_kama ^GSPC 2011-01-04 2012-12-31 1.0 -0.1 -0.05 -0.2 -0.23 0.06 -0.04
23 ts_tsi_^GSPC No ts_tsi ^GSPC 2011-01-04 2012-12-31 0.95 -0.17 -0.09 -0.47 -0.24 0.06 -0.04
24 all_^GSPC No all ^GSPC 2011-01-04 2012-12-31 1.0 -0.02 -0.01 0.04 -0.22 0.05 -0.07
27 Long-Only Trade Strategy for ^GSPC No long ^GSPC 2011-01-04 2012-12-31 1.0 0.12 0.06 0.4 -0.19 0.05 -0.07
In [ ]:
tsExecuteEngine.getSummaryMetrics().query('trade_asset == "^GSPC" ').T.head(60)

Persist Backtest to DB (optional )

In [ ]:
session.add( tsExecuteEngine )

try :
    session.commit()
except Exception as inst:
    print(type(inst))    # the exception instance
    print(inst)
    print(inst.args)     # arguments stored in .args
    session.rollback()   # roll back changes
finally:
    print(" done")
In [ ]:
 

Full Tearsheet Report for a Trade Strategy

Composite Nasdaq Trade Strategy vs Nasdaq

In [168]:
BacktestReports.createTearsheetReport(\
                    backtest                   = tsExecuteEngine,
                    ta_reg_item_name           = "all_^IXIC",
                    ta_reg_item_benchmark_name = "Long-Only Trade Strategy for ^IXIC ", # optional
                    report_type                = "full" )

Performance Metrics

                           Strategy    Benchmark
-------------------------  ----------  -----------
Start Period               2011-01-04  2011-01-04
End Period                 2012-12-31  2012-12-31
Risk-Free Rate             0.0%        0.0%
Time in Market             100.0%      100.0%

Cumulative Return          28.41%      12.18%
CAGR%                      13.38%      5.94%

Sharpe                     0.7         0.38
Sortino                    1.06        0.54
Sortino/√2                 0.75        0.38

Max Drawdown               -22.15%     -18.71%
Longest DD Days            266         277
Volatility (ann.)          20.96%      20.75%
R^2                        0.08        0.08
Calmar                     0.6         0.32
Skew                       0.11        -0.29
Kurtosis                   3.09        3.24

Expected Daily %           0.05%       0.02%
Expected Monthly %         1.05%       0.48%
Expected Yearly %          13.32%      5.92%
Kelly Criterion            2.6%        5.8%
Risk of Ruin               0.0%        0.0%
Daily Value-at-Risk        -2.11%      -2.12%
Expected Shortfall (cVaR)  -2.11%      -2.12%

Gain/Pain Ratio            0.13        0.07
Gain/Pain (1M)             1.07        0.51

Payoff Ratio               0.99        0.99
Profit Factor              1.13        1.07
Common Sense Ratio         1.33        1.09
CPC Index                  0.58        0.56
Tail Ratio                 1.18        1.02
Outlier Win Ratio          3.91        4.17
Outlier Loss Ratio         3.57        3.4

MTD                        4.51%       0.31%
3M                         -1.31%      -3.1%
6M                         0.71%       2.88%
YTD                        3.85%       15.9%
1Y                         3.85%       15.9%
3Y (ann.)                  13.38%      5.94%
5Y (ann.)                  13.38%      5.94%
10Y (ann.)                 13.38%      5.94%
All-time (ann.)            13.38%      5.94%

Best Day                   5.29%       5.29%
Worst Day                  -6.9%       -6.9%
Best Month                 9.74%       11.14%
Worst Month                -6.81%      -7.19%
Best Year                  23.65%      15.9%
Worst Year                 3.85%       -3.21%

Avg. Drawdown              -4.32%      -3.36%
Avg. Drawdown Days         34          37
Recovery Factor            1.28        0.65
Ulcer Index                1.08        1.08

Avg. Up Month              2.5%        4.14%
Avg. Down Month            -4.14%      -2.51%
Win Days %                 51.5%       53.09%
Win Month %                75.0%       54.17%
Win Quarter %              62.5%       50.0%
Win Year %                 100.0%      50.0%
Beta                       0.29        -
Alpha                      0.12        -
None

5 Worst Drawdowns

Start Valley End Days Max Drawdown 99% Max Drawdown
1 2011-02-22 2011-08-08 2011-09-07 197 -22.151774 -16.385371
2 2011-09-14 2011-10-14 2011-11-04 51 -14.116201 -13.698558
3 2012-04-09 2012-06-08 2012-12-31 266 -12.779965 -11.894544
4 2011-11-16 2011-11-25 2011-12-09 23 -9.108071 -8.416839
5 2012-03-13 2012-03-22 2012-04-04 22 -3.438963 -3.294040

Strategy Visualization

Composite DJI Trade Strategy vs DJI

In [169]:
BacktestReports.createTearsheetReport(\
                    backtest                   = tsExecuteEngine,
                    ta_reg_item_name           = "all_^DJI",
                    ta_reg_item_benchmark_name = "Long-Only Trade Strategy for ^DJI ", # optional
                    report_type                = "full" )

Performance Metrics

                           Strategy    Benchmark
-------------------------  ----------  -----------
Start Period               2011-01-04  2011-01-04
End Period                 2012-12-31  2012-12-31
Risk-Free Rate             0.0%        0.0%
Time in Market             100.0%      100.0%

Cumulative Return          18.33%      12.26%
CAGR%                      8.82%       5.98%

Sharpe                     0.58        0.43
Sortino                    0.86        0.59
Sortino/√2                 0.61        0.42

Max Drawdown               -20.09%     -16.79%
Longest DD Days            133         277
Volatility (ann.)          17.21%      17.02%
R^2                        0.0         0.0
Calmar                     0.44        0.36
Skew                       0.04        -0.41
Kurtosis                   3.55        3.7

Expected Daily %           0.03%       0.02%
Expected Monthly %         0.7%        0.48%
Expected Yearly %          8.78%       5.95%
Kelly Criterion            4.2%        9.47%
Risk of Ruin               0.0%        0.0%
Daily Value-at-Risk        -1.74%      -1.73%
Expected Shortfall (cVaR)  -1.74%      -1.73%

Gain/Pain Ratio            0.11        0.08
Gain/Pain (1M)             0.93        0.6

Payoff Ratio               1.12        1.12
Profit Factor              1.11        1.08
Common Sense Ratio         1.3         1.06
CPC Index                  0.62        0.63
Tail Ratio                 1.17        0.98
Outlier Win Ratio          3.59        3.9
Outlier Loss Ratio         4.38        4.13

MTD                        1.03%       0.6%
3M                         1.19%       -2.47%
6M                         1.13%       1.74%
YTD                        13.74%      7.24%
1Y                         13.74%      7.24%
3Y (ann.)                  8.82%       5.98%
5Y (ann.)                  8.82%       5.98%
10Y (ann.)                 8.82%       5.98%
All-time (ann.)            8.82%       5.98%

Best Day                   4.61%       4.23%
Worst Day                  -5.53%      -5.53%
Best Month                 13.15%      9.52%
Worst Month                -5.01%      -6.2%
Best Year                  13.74%      7.24%
Worst Year                 4.04%       4.68%

Avg. Drawdown              -3.45%      -2.31%
Avg. Drawdown Days         24          27
Recovery Factor            0.91        0.73
Ulcer Index                1.06        1.08

Avg. Up Month              2.19%       1.84%
Avg. Down Month            -2.05%      -2.73%
Win Days %                 49.3%       52.1%
Win Month %                58.33%      66.67%
Win Quarter %              62.5%       62.5%
Win Year %                 100.0%      100.0%
Beta                       0.06        -
Alpha                      0.1         -
None

5 Worst Drawdowns

Start Valley End Days Max Drawdown 99% Max Drawdown
1 2011-05-11 2011-08-08 2011-09-21 133 -20.092738 -16.926920
2 2011-11-14 2011-12-07 2012-03-13 120 -10.702331 -10.322832
3 2012-04-19 2012-05-18 2012-06-29 71 -8.870995 -8.334880
4 2011-10-06 2011-11-01 2011-11-11 36 -7.587114 -7.585521
5 2012-11-19 2012-12-18 2012-12-31 42 -6.034787 -5.724283

Strategy Visualization

Portfolio

In [170]:
BacktestReports.createTearsheetReport(\
                    backtest                   = tsExecuteEngine,
                    ta_reg_item_name           = "Portfolio of US-Indexes with TechAnal & AI Trading Models, and Long strategies",
                    ta_reg_item_benchmark_name = None, # optional
                    report_type                = "full" )

Performance Metrics

                           Strategy
-------------------------  ----------
Start Period               2011-01-04
End Period                 2012-12-31
Risk-Free Rate             0.0%
Time in Market             100.0%

Cumulative Return          10.04%
CAGR%                      4.92%

Sharpe                     0.58
Sortino                    0.85
Sortino/√2                 0.6

Max Drawdown               -10.64%
Longest DD Days            252
Volatility (ann.)          9.0%
Calmar                     0.46
Skew                       -0.15
Kurtosis                   3.31

Expected Daily %           0.02%
Expected Monthly %         0.4%
Expected Yearly %          4.9%
Kelly Criterion            5.14%
Risk of Ruin               0.0%
Daily Value-at-Risk        -0.91%
Expected Shortfall (cVaR)  -0.91%

Gain/Pain Ratio            0.12
Gain/Pain (1M)             0.66

Payoff Ratio               1.18
Profit Factor              1.12
Common Sense Ratio         1.35
CPC Index                  0.64
Tail Ratio                 1.21
Outlier Win Ratio          3.89
Outlier Loss Ratio         4.85

MTD                        1.01%
3M                         -1.8%
6M                         0.05%
YTD                        7.71%
1Y                         7.71%
3Y (ann.)                  4.92%
5Y (ann.)                  4.92%
10Y (ann.)                 4.92%
All-time (ann.)            4.92%

Best Day                   2.1%
Worst Day                  -2.78%
Best Month                 5.32%
Worst Month                -3.52%
Best Year                  7.71%
Worst Year                 2.17%

Avg. Drawdown              -1.18%
Avg. Drawdown Days         21
Recovery Factor            0.94
Ulcer Index                1.06

Avg. Up Month              1.86%
Avg. Down Month            -1.59%
Win Days %                 48.7%
Win Month %                58.33%
Win Quarter %              50.0%
Win Year %                 100.0%
None

5 Worst Drawdowns

Start Valley End Days Max Drawdown 99% Max Drawdown
1 2011-03-04 2011-08-08 2011-11-11 252 -10.642112 -9.051853
2 2012-04-26 2012-05-18 2012-09-06 133 -5.370260 -5.015202
3 2011-11-16 2011-11-25 2012-01-17 62 -4.817825 -4.580090
4 2012-11-08 2012-12-11 2012-12-31 53 -4.146542 -4.088048
5 2012-04-03 2012-04-10 2012-04-25 22 -3.034206 -2.361398

Strategy Visualization

In [ ]:
 

HTML Tearsheet Reports

In [167]:
BacktestReports.createHTMLTearsheetReport(\
                    backtest                   = tsExecuteEngine,
                    ta_reg_item_name           = "all_^IXIC",
                    ta_reg_item_benchmark_name = "Long-Only Trade Strategy for ^IXIC ", # optional
                    title                      = 'Strategy Tearsheet', 
                    download_filename          = 'ts-tearsheet.html' ) 
In [ ]: